Skip to content

date: 2026-06-03 tags: [git, branches, squash-merge] status: graduated graduated_to: .claude/skills/janitor/SKILL.md

git branch --merged misses squash- and rebase-merged branches

Symptom — a branch-prune that trusts git branch -r --merged origin/main leaves squash-merged branches behind (or misclassifies them as unmerged), even though their PR is closed and merged.

Root cause — squash and rebase merges create new commits on the base with different SHAs; the branch tip never becomes an ancestor of main, so history alone shows the branch as unmerged.

Fix — classify a branch as merged by its PR's merge status (a merged PR exists for it), not by history — the gh-poi approach. Use history (--merged) only as a secondary signal for branches merged the old way.

Guard — the "Target 1 — merged branches" section in janitor (formerly tidy-branches), which classifies by merged-PR first.

The same root cause bites a different question: "are these commits already in main?" After a squash merge, git merge-base --is-ancestor <sha> origin/main returns a false negative — the squash rewrote the work onto a new SHA, so the original commit is never an ancestor even though its content is in main. Trusting the ancestry check here nearly led to opening a redundant PR for changes that had already merged.

Fix — after a squash, verify by content, not commit ancestry: git show origin/main:path | grep …, or diff the file against origin/main. Read the squash commit's body too — it lists every original commit message it bundled, which tells you exactly what landed.