# Clean Branches

> Use when cleaning up local branches, deleting merged branches, pruning stale or gone branches, or…

Use when cleaning up local branches, deleting merged branches, pruning stale or gone branches, or tidying `git branch` output. Removes branches whose work has already landed, including squash-merged PRs.

- Page: https://ss33.ai/skills/tartinerlabs/clean-branches-41486278073
- Publisher: tartinerlabs
- Category: [Software Development](https://ss33.ai/skills/category/software-development-t44z8z) › [Source control & code review](https://ss33.ai/skills/category/software-development-t44z8z/source-control-and-code-review-jebezw)
- License: MIT
- Source: https://github.com/tartinerlabs/skills/blob/9f8a6f174d310717f92d3e62577adf4aeb9b06ba/plugins/workflow/skills/clean-branches/SKILL.md

## Skill

SKILL.md: https://ss33.ai/api/v1/ss33/download/tartinerlabs/clean-branches-41486278073

You delete local branches whose work has already landed, and leave everything else alone.

## Workflow

1. Sync remote state: `git fetch --prune`. Note the current branch and any branches checked out in worktrees (`git worktree list`) — never delete those
2. **Native pass (git 2.56+)**: preview with `git branch --dry-run --delete-merged <remote>`, then run it without `--dry-run`. It deletes branches whose tip is reachable from their still-existing upstream, and honours `branch.<name>.deleteMerged=false` opt-outs. On older git, skip to step 3
3. **Gap pass**: `--delete-merged` deliberately skips a branch whose upstream is gone and a branch with no upstream — which is where most merged PR branches end up once the host deletes the head branch. Build a candidate list from `git branch -vv` (`: gone]` upstreams and branches with no upstream), then keep a candidate only when one of these confirms it landed:
   - `git branch --merged <default-branch>` lists it (fast-forward or merge commit)
   - Its PR/MR is merged — GitHub: `gh pr list --state merged --head <branch>`; GitLab: `glab mr list --merged --source-branch <branch>`. This catches squash and rebase merges, whose commits are not reachable from the default branch
4. Show the combined list with the evidence per branch (e.g. `#93 merged`, `merged into main`) and confirm before deleting. Delete with `git branch -d`; a squash-merged branch needs `-D`, which is safe only because step 3 proved its PR merged
5. Report what was deleted and what was kept, with the reason for each kept branch — closed-unmerged PR, no PR, upstream ahead, checked out

## Keep, don't guess

A branch with a closed-but-unmerged PR or no PR at all may hold unfinished work. List it as kept and let the user decide; never delete it on age or name alone. Remote branches are out of scope — this skill only touches local refs.
