Prune Merged Branches
Remove local branches that have already been merged into remote main.
Usage
- •
/git-prune-merged- List and prune merged branches (with confirmation) - •
/git-prune-merged --dry-run- Only list branches that would be pruned
Instructions
- •
Fetch latest from remote:
bashgit fetch origin main --prune
- •
Find merged branches (store as
MERGED_BRANCHES):Detect branches merged via two methods:
Method A - Regular merges:
bashgit branch --merged origin/main | grep -v '^\*' | grep -v 'main' | grep -v 'master'
Method B - Squash merges (remote branch deleted after PR merge):
bashgit branch -vv | grep ': gone]' | awk '{print $1}'Combine both lists, removing duplicates. This catches:
- •Branches with commits directly in origin/main history (regular merge)
- •Branches whose remote tracking branch was deleted after merge (squash merge)
- •
Handle dry-run mode:
- •If
$ARGUMENTScontains--dry-run:- •Display the list of branches that would be pruned
- •Exit without deleting
- •If
- •
Display branches for confirmation:
- •
If
MERGED_BRANCHESis empty:codeNo merged branches to prune. All local branches have unmerged commits.
Exit here.
- •
Otherwise, display:
codeFound merged branches to prune: | Branch | Last Commit | |--------|-------------| | feature/auth | 3 days ago | | fix/login-bug | 1 week ago |
- •
Use
AskUserQuestionto confirm:- •"Delete all" - Delete all listed branches
- •"Select branches" - Let user choose which to delete
- •"Cancel" - Exit without deleting
- •
- •
Delete confirmed branches:
For branches detected via Method A (regular merge):
bashgit branch -d <branch-name>
For branches detected via Method B (squash merge / gone remote):
bashgit branch -D <branch-name>
Note: Method A branches use
-das a safety check. Method B branches require-Dbecause their commits aren't in main's history (they were squashed). The "gone" remote is the indicator that the PR was merged. - •
Report results:
codePruned branches: - feature/auth - fix/login-bug Kept branches: - (none) Remaining local branches: 3
Example Output
$ /git-prune-merged Fetching latest from origin... Found merged branches to prune: | Branch | Last Commit | |--------|-------------| | docs/update-readme | 2 days ago | | feature/add-auth | 1 week ago | | fix/typo | 3 weeks ago | ? Delete these branches? > Delete all Select branches Cancel Pruned branches: - docs/update-readme - feature/add-auth - fix/typo Remaining local branches: 2 (main, feature/in-progress)
Important Notes
- •Squash merge support: Detects branches whose remote was deleted after PR merge, even if squash-merged
- •Safe deletion: Regular merges use
-d; squash merges use-D(safe because remote deletion confirms merge) - •Protected branches: Never deletes
main,master, or the current branch - •Remote cleanup: Run
git fetch --pruneseparately to clean up stale remote-tracking references - •Worktrees: Branches in use by worktrees cannot be deleted; detach the worktree first
Known Edge Cases
Branch tracking origin/main instead of its own remote
Symptom: A squash-merged branch isn't detected even after git fetch --prune.
Cause: The branch was configured to track origin/main directly instead of origin/<branch-name>. When checking git branch -vv, it shows [origin/main: ahead X] instead of [origin/<branch-name>: gone].
Detection: Method B (git branch -vv | grep ': gone]') fails because origin/main still exists.
Resolution: These branches require manual identification. Check git branch -vv for branches showing [origin/main: ahead X] where the remote branch no longer exists:
# Check if the branch's expected remote exists git branch -r | grep "<branch-name>" # If no output, the branch was likely merged and can be deleted with -D
Example: Branch feature/user-settings tracked origin/main instead of origin/feature/user-settings. After the PR was squash-merged and the remote deleted, it showed [origin/main: ahead 3] instead of : gone].