Appearance
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.
Related instance — the same trap when checking if work landed in main
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.