Git: custom command with powershell
One of the most annoying thing that I have to do every once in a while is to clean up all the dead references in my git repositories. When the branches get integrated through PRs, they have no reason to continue living on my computer. We have configured Azure DevOps to automatically delete the merged branch on the remote server but we still have them locally on our computers.
I have addressed the issue by creating my own git subcommand: `git putz`.
For the record, `putz` means cleaning in german. It is a short and fun name for this operation ^^
- Create a script and save it somewhere in your path
I have picked powershell because my workstation runs on Windows. The same can be achieved with other script languages.
# Script to delete merged, obsolete, and untracked git branches
# Fetch latest changes from remote and prune references
Write-Host "Fetching latest changes and pruning references..." -ForegroundColor Yellow
git fetch --prune
# Get current branch
$currentBranch = git rev-parse --abbrev-ref HEAD
# Get list of merged branches (excluding main, master, and develop)
$mergedBranches = git branch --merged |
Where-Object { $_.Trim() -notmatch '^(\*|\s*(master|main|dev)$)' } |
ForEach-Object { $_.Trim() }
# Get list of branches where the remote is gone
$goneBranches = git branch -v |
Where-Object { $_ -match '\[gone\]' } |
ForEach-Object { $_.Split()[0] } |
Where-Object { $_ -notmatch '^(\*|\s*(master|main|dev)$)' }
# Get list of local branches with no upstream tracking branch
$untrackedBranches = git branch -vv |
Where-Object { $_ -notmatch '\[.+\]' } |
ForEach-Object {
if ($_ -match '^\*?\s*(\S+)') {
$matches[1]
}
} |
Where-Object { $_ -notmatch '^(master|main|dev)$' -and $_ -ne $currentBranch }
if ($mergedBranches.Count -eq 0 -and $goneBranches.Count -eq 0 -and $untrackedBranches.Count -eq 0) {
Write-Host "No branches to clean up!" -ForegroundColor Green
exit 0
}
# Display branches to be deleted
Write-Host "`nThe following branches will be deleted:" -ForegroundColor Yellow
if ($mergedBranches.Count -gt 0) {
Write-Host "`nMerged branches:" -ForegroundColor Cyan
$mergedBranches | ForEach-Object { Write-Host " - $_" }
}
if ($goneBranches.Count -gt 0) {
Write-Host "`nBranches with gone remotes:" -ForegroundColor Cyan
$goneBranches | ForEach-Object { Write-Host " - $_" }
}
if ($untrackedBranches.Count -gt 0) {
Write-Host "`nLocal branches with no upstream:" -ForegroundColor Cyan
$untrackedBranches | ForEach-Object { Write-Host " - $_" }
}
# Prompt for confirmation
Write-Host "`nDo you want to proceed with deletion? (Y/N)" -ForegroundColor Yellow
$confirmation = Read-Host
if ($confirmation -eq 'Y' -or $confirmation -eq 'y') {
# Delete merged branches
foreach ($branch in $mergedBranches) {
Write-Host "Deleting merged branch: $branch" -ForegroundColor Cyan
git branch -d $branch
}
# Delete gone branches
foreach ($branch in $goneBranches) {
Write-Host "Deleting gone branch: $branch" -ForegroundColor Cyan
git branch -D $branch
}
# Delete untracked branches
foreach ($branch in $untrackedBranches) {
Write-Host "Deleting untracked branch: $branch" -ForegroundColor Cyan
git branch -D $branch
}
Write-Host "`nBranch cleanup completed!" -ForegroundColor Green
} else {
Write-Host "`nOperation cancelled." -ForegroundColor Yellow
}
The script lists merged, gone and untracked branches, asks for confirmation and deletes theme all at once. What a relief !
2. Create an alias for git
Simply run the following command by making sure to fix the script path:
git config --global alias.putz "!powershell.exe -File C:/Tools/git_delete_gone_branches.ps1"
That's it, now run `git putz`:
The following branches will be deleted:
Local branches with no upstream:
- feature/cnc_auto_reset_manual
- features/architecture_updates
- features/barrier_crossed_guard
- features/blazor_server
- features/cnc_wait_resilience
- features/dummy_branch
- features/dummy_to_merge
- features/emergency_ack
...
Do you want to proceed with deletion? (Y/N)
Y
Deleting untracked branch: feature/cnc_auto_reset_manual
Deleted branch feature/cnc_auto_reset_manual (was 81a3233d7).
Deleting untracked branch: features/architecture_updates
Deleted branch features/architecture_updates (was 6ccd947b9).
Deleting untracked branch: features/barrier_crossed_guard
Deleted branch features/barrier_crossed_guard (was 3a1e85cef).
Deleting untracked branch: features/blazor_server
Deleted branch features/blazor_server (was dec07d9be).
...
Branch cleanup completed!