squash-merge-content-preservation-vs-ancestor-checklisted
Install: claude install-skill wan-huiyan/agent-traffic-control
# Squash Merge Content Preservation vs Ancestor Check
## Problem
Your verification script says:
```bash
git merge-base --is-ancestor 0b6303e76 origin/main && echo "OK" || echo "MISSING"
# Prints: MISSING
```
… but `wc -l <signature-file>` returns the expected line counts and `grep -c
<signature-string>` returns ≥ the expected ref count. The exit code from
`is-ancestor` is non-zero **even though every byte of the upstream work is
preserved on the target branch**. The "MISSING" verdict is wrong.
Root cause: a squash merge collapses every commit on the source branch into a
**single new commit** on the target. The original SHAs (including the upstream
commit you're checking) never appear in the target's history. `is-ancestor`
returns "false" because the SHA truly isn't an ancestor of the merge commit —
but the SHA's *content* is preserved verbatim inside the squash commit.
This trap fires whenever:
- A handoff prompt or skill mixes ancestor-based checks with content-based
checks for the same preservation claim
- The handoff was written before the merge mode was decided
- The verification template assumed fast-forward / no-ff (which preserves
lineage) but the actual merge used squash
## Context / Trigger Conditions
You're in the right place if **all** of these are true:
- A propagation-style PR (`branch-A → branch-B`, often 20+ commits ahead) has
recently merged
- The verification step instructs you to check `git merge-base --is-ancestor
<upstream-sha> <target-br