Last active
October 26, 2020 08:26
-
-
Save michaelkc/d44b4dd79770a4624e8d28fdc47c8559 to your computer and use it in GitHub Desktop.
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
$ErrorActionPreference = "Stop" | |
Set-StrictMode -Version Latest | |
$git = "git.exe" | |
$master = "master" | |
$protectedBranches = "$master|main" | |
# This script was adapted from ZSH script at | |
# https://blog.takanabe.tokyo/en/2020/04/remove-squash-merged-local-git-branches/ | |
# It is supplemented with code to track and pull all remote branches, to make sure all | |
# remote branches ready for deletion are accounted for | |
# It outputs the commands needed to delete the remote branches matching the ones it | |
# deletes locally. | |
function track_all_remote_branches() { | |
$localBranches = &$git branch -l | Foreach-Object { $_.Trim() } | |
&$git branch -r | | |
Foreach-Object { $_.Trim() } | | |
Where-Object { -not ($_ -match '\->') } | | |
Where-Object { -not ($_ -match "(^\*|$protectedBranches)") } | | |
ForEach-Object { | |
$local = $_ -Replace 'origin/', '' | |
if ($localBranches.Contains($local)) { | |
Write-Host "Already tracking $_" | |
} | |
else { | |
Write-Host "Tracking $_" | |
&$git branch --track "$local" "$_" | |
} | |
} | |
&$git fetch --all | |
&$git pull --all | |
} | |
function git_prune_remote() { | |
Write-Host "Start removing out-dated remote merged branches" | |
&$git fetch --prune | Out-Null | |
Write-Host "Finish removing out-dated remote merged branches" | |
} | |
function git_remove_merged_local_branch() { | |
Write-Host "Start removing out-dated local merged branches" | |
$mergedLocalBranches = &$git branch --merged | Where-Object { -not ($_ -match "(^\*|$protectedBranches)") } | |
$deletedBranches = New-Object System.Collections.Generic.List[string] | |
foreach ($branch in $mergedLocalBranches) { | |
$branch = $branch.Trim() | |
$deletedBranches.Add($branch) | |
Write-Host "Removing $branch locally" | |
&$git branch -D $branch | Out-Null | |
} | |
Write-Host "Finish removing out-dated local merged branches" | |
return $deletedBranches | |
} | |
# When we use `Squash and merge` on GitHub, | |
# `&$git branch --merged` cannot detect the squash-merged branches. | |
# As a result, git_remove_merged_local_branch() cannot clean up | |
# unused local branches. This function detects and removes local branches | |
# when remote branches are squash-merged. | |
# | |
# There is an edge case. If you add suggested commits on GitHub, | |
# the contents in local and remote are different. As a result, | |
# This clean up function cannot remove local squash-merged branch. | |
function git_remove_squash_merged_local_branch() { | |
Write-Host "Start removing out-dated local squash-merged branches" | |
&$git checkout -q $master | |
$branches = &$git for-each-ref refs/heads/ "--format=%(refname:short)" | |
$deletedBranches = New-Object System.Collections.Generic.List[string] | |
foreach ($branch in $branches) { | |
#Write-Host $branch | |
$ancestor = $(&$git merge-base $master $branch) | |
#Write-Host "A: $ancestor" | |
$rp = &$git rev-parse "$branch^{tree}" | |
#Write-Host "RP: $rp" | |
$ct = &$git commit-tree "$rp" -p $ancestor -m _ | |
#Write-Host "CT: $ct" | |
$cherry = &$git cherry $master "$ct" | |
#Write-Host "Cherry: $cherry" | |
if ($cherry -match "\-.*") { | |
Write-Host "Removing $branch locally" | |
&$git branch -D $branch | Out-Null | |
$deletedBranches.Add($branch) | |
} | |
} | |
Write-Host "Finish removing out-dated local squash-merged branches" | |
return $deletedBranches | |
} | |
# Clean up remote and local branches | |
track_all_remote_branches | |
git_prune_remote | |
$mergedBranches = git_remove_merged_local_branch | |
$squashMergedBranches = git_remove_squash_merged_local_branch | |
Write-Host "Script to delete remote branches" | |
foreach ($b in ($mergedBranches + $squashMergedBranches | Select-Object -uniq)) { | |
Write-Output "git push origin --delete $b" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment