Created
July 3, 2025 06:26
-
-
Save readingdancer/7ec5825923dc5e78104818bad67fabfe to your computer and use it in GitHub Desktop.
A PowerShell script that automatically rebases multiple pull request branches that were created from a specific old dev commit onto the latest dev branch.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| param( | |
| [Parameter(Position=0, Mandatory=$false)] | |
| [string]$OldDevCommit, | |
| [switch]$DryRun | |
| ) | |
| function Show-Help { | |
| Write-Host "Usage: .\Rebase-PRs.ps1 <old-dev-commit> [-DryRun]" | |
| Write-Host "" | |
| Write-Host "Example:" | |
| Write-Host " .\Rebase-PRs.ps1 abc123def4567890" | |
| Write-Host "" | |
| Write-Host "Options:" | |
| Write-Host " -DryRun Show what would happen without changing anything." | |
| Write-Host "" | |
| Write-Host "This script rebases only PR branches branched from the specified old dev commit" | |
| Write-Host "onto the latest dev branch and updates them on the remote." | |
| Write-Host "" | |
| Write-Host "Note: This script will never operate on the 'main' branch for safety." | |
| } | |
| if (-not $OldDevCommit) { | |
| Show-Help | |
| exit 1 | |
| } | |
| $remote = "origin" | |
| $devBranch = "dev" | |
| $mainBranch = "main" | |
| $protectedBranches = @($devBranch, $mainBranch) | |
| $ErrorActionPreference = "Stop" | |
| # Safety check: Ensure we're not currently on main branch | |
| $currentBranch = git rev-parse --abbrev-ref HEAD | |
| if ($currentBranch -eq $mainBranch) { | |
| Write-Host "❌ Error: Currently on '$mainBranch' branch. This script will not operate on the main branch for safety." | |
| Write-Host "Please switch to a different branch before running this script." | |
| exit 1 | |
| } | |
| Write-Host "Using old dev commit: $OldDevCommit" | |
| if ($DryRun) { | |
| Write-Host "Running in DRY RUN mode..." | |
| } | |
| Write-Host "`nFetching latest $devBranch..." | |
| git checkout $devBranch | |
| git fetch $remote | |
| git pull $remote $devBranch | |
| Write-Host "`nBuilding list of remote branches..." | |
| $remoteBranches = git ls-remote --heads $remote | ForEach-Object { | |
| ($_ -split "refs/heads/")[-1].Trim() | |
| } | Where-Object { | |
| # Exclude protected branches (dev and main) | |
| $_ -notin $protectedBranches | |
| } | |
| if (-not $remoteBranches) { | |
| Write-Host "No remote branches found (excluding protected branches: $($protectedBranches -join ', ')). Exiting." | |
| exit 0 | |
| } | |
| Write-Host "Found these remote branches (excluding protected branches):`n$($remoteBranches -join "`n")" | |
| foreach ($branch in $remoteBranches) { | |
| Write-Host "`nProcessing branch: $branch" | |
| # Additional safety check: Never process main branch | |
| if ($branch -eq $mainBranch) { | |
| Write-Host " ⚠️ Skipping '$mainBranch' branch for safety (this should not happen due to filtering)." | |
| continue | |
| } | |
| # Fetch the branch tip from the remote (safer and simpler) | |
| git fetch $remote $branch | |
| # Compute fork point with dev | |
| $forkPoint = git merge-base "$remote/$branch" $devBranch | |
| Write-Host " -> Fork point is $forkPoint" | |
| if ($forkPoint -eq $OldDevCommit) { | |
| Write-Host " -> Branch $branch was based on old dev ($OldDevCommit)." | |
| if ($DryRun) { | |
| Write-Host " [DryRun] Would rebase $branch onto latest dev and push." | |
| continue | |
| } | |
| # Create or update local branch tracking the remote tip | |
| if (git show-ref --verify --quiet "refs/heads/$branch") { | |
| git branch -f "$branch" "$remote/$branch" | |
| } else { | |
| git branch "$branch" "$remote/$branch" | |
| } | |
| # Final safety check before checkout | |
| if ($branch -eq $mainBranch) { | |
| Write-Host " ❌ Error: Attempted to checkout '$mainBranch' branch. Skipping for safety." | |
| continue | |
| } | |
| git checkout "$branch" | |
| try { | |
| git rebase $devBranch | |
| } catch { | |
| Write-Host " !! Conflict occurred while rebasing $branch. Resolve manually." | |
| exit 1 | |
| } | |
| git push $remote "$branch" --force-with-lease | |
| Write-Host " -> Rebased and pushed $branch successfully." | |
| } else { | |
| Write-Host " -> Skipping $branch (fork point doesn't match old dev)." | |
| } | |
| } | |
| Write-Host "`n✅ Done!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment