Catalog, verify, and clean up stale git branches. Supports squash-merge workflows. USE THIS SKILL when the user wants to clean up old branches, find stale branches, or tidy their git repo.
Scan all branches, categorize by status, present for review, and delete approved branches.
Auto-detect the upstream remote and target branch, then confirm with the user.
Run git remote -v and look for:
upstream — common for fork workflowsupstream, check if origin points to the canonical repo (not a fork)Run git remote show <upstream> or check for common default branches:
main, master, dev (in that order of preference)git symbolic-ref refs/remotes/<upstream>/HEADPresent the detected upstream remote and target branch. Ask the user to confirm or override. Example:
Detected upstream:
upstream→akkadotnet/akka.net, target branch:devIs this correct?
git fetch <upstream> --quiet
git fetch origin --prune --quiet
Run git branch -vv --no-color to get all local branches with:
Also run git branch -r --no-color to get remote branches on origin (excluding upstream branches — those aren't ours).
For each branch, record:
origin/<name> existsSkip tracking branches (dev, main, master) — never suggest deleting these.
For each non-tracking branch, determine its category. Try these checks in order - the first match wins.
If is_current is true, category = current (never delete).
Compare the SHA against all other branches. If another branch has the exact same SHA and a different name, this is likely an old name.
Category = renamed if:
Record which branch it was renamed to.
Step A — Try git branch --merged:
git branch --merged <upstream>/<target>
If the branch appears in this list, it was merged (not squash-merged). Category = merged.
Step B — Try PR-based verification (for squash merges):
If the branch was NOT in the --merged list, check if it has a merged PR.
Use available tools to search for PRs from the branch. Try these in order:
gh CLI — gh pr list --head <branch-name> --state merged --json numberaz CLI — az repos pr list --source-branch <branch-name> --status completedIf a merged PR is found, verify the squash commit exists on the target branch:
git log --oneline <upstream>/<target> --grep="#<pr-number>" -1
If found, category = merged. Record the PR number.
Step C — No merged PR found:
Continue to next check.
Search for open PRs from this branch using available tools (GitHub MCP, Azure DevOps MCP, gh CLI, or az CLI - same
priority as step 3.3B).
If found, category = active_pr. Record the PR number.
If none of the above matched, category = unknown.
Group branches by action and present using a card-per-branch format.
DELETE (<count> branches)
═════════════════════════
Merged PRs (local + origin)
───────────────────────────
✓ <branch-name>
PR #<number> merged │ <sha>
├─ delete: git branch -D <branch-name>
├─ delete: git push origin --delete <branch-name>
└─ undo: git branch <branch-name> <full-sha>
Renamed (old names)
───────────────────
→ <old-branch-name>
Renamed to <new-branch-name> │ <sha>
├─ delete: git branch -D <old-branch-name>
└─ undo: git branch <old-branch-name> <full-sha>
UNKNOWN (<count> branches — need your input)
════════════════════════════════════════════
? <branch-name>
No PR found │ local only │ <sha>
Last commit: "<commit subject>"
KEEPING (<count> branches)
══════════════════════════
● <branch-name> PR #<number> open
─ dev
─ master
-D (force) for delete commands, not -d, because squash-merged branches won't be detected as merged by git.After presenting the view, ask the user which branches to delete:
For approved branches:
dev)git branch -D <name>git push origin --delete <name>Run git fetch origin --prune to clean up stale remote tracking refs.
Report final state: how many branches remain.
gh CLI, or az CLI is available, skip PR-based
verification. Categorize all non---merged branches as unknown and note that PR status couldn't be checked./prune
1. Detect repo layout → find upstream remote + target branch
2. Scan branches → enumerate local + remote, collect metadata
3. Categorize → merged / renamed / active PR / unknown
4. Present → card-per-branch grouped by action
5. Confirm + execute → user approves, delete local + remote