--- name: squash-branch description: Use when collapsing a feature branch into a single commit before opening or merging a PR. Covers the non-interactive squash, dropping co-author trailers, and verifying the tree is unchanged. --- # Squash branch Collapse all of a branch's commits into one, authored by the committer, with a clean message and no co-author trailers. Interactive rebase (`git rebase -i`) is not available in this environment, so the squash uses `git reset --soft` against the base, which produces the identical end state. ## When to use Use when a feature branch has several work-in-progress commits that should land as one commit. Do NOT use on a shared branch others have based work on (rewriting its history breaks their clones), and do NOT run any git command here without explicit user request, per the repo git policy. ## Files that change None. This operates on git history, not the working tree. The tree at HEAD is byte-for-byte identical before and after; only the commit history collapses. ## Procedure 1. Confirm the base and that the branch is ahead of it with nothing behind: `git rev-list --count ..HEAD` (commits to squash) and `git rev-list --count HEAD..` (must be 0; rebase onto `` first if not). 2. Record the current tree to verify the squash later: `git rev-parse HEAD^{tree}`. 3. Collapse to staged changes without moving the working tree: `git reset --soft `. 4. Stage any intended uncommitted additions with `git add`, leaving unrelated working-tree changes out. 5. Commit once with a clean message and no co-author or generated-by trailers: `git commit`. The commit is authored by the configured git identity. 6. Verify nothing changed: `git rev-parse HEAD^{tree}` must equal the value from step 2, and `git log --oneline ..HEAD` must show exactly one commit. ## Gates - The post-squash tree hash must equal the pre-squash tree hash (step 6); a mismatch means content was dropped or added, not just recommitted. - `git log --oneline ..HEAD` shows a single commit. ## Pitfalls - `git reset --soft` leaves the index and working tree untouched, so uncommitted or untracked files are still present after it; stage deliberately in step 4 so unrelated changes do not get folded into the squash. - Squashing rewrites history, so a branch already pushed needs a force push (`--force-with-lease`), which is an outward-facing action the user must approve. - Writing a fresh commit message drops any co-author or generated-by trailers from the original commits, which is the intended cleanup; do not carry them forward.