Purpose
Squash all branch commits since merge-base into a single curated commit safely.
Location
git/squash-branch.sh
Preconditions
- Required tools:
bash,git,date - Required permissions: branch rewrite rights; push permissions when
--push - Required environment variables: none
Arguments
| Flag | Required | Default | Description |
|---|---|---|---|
--base REF |
Yes | N/A | Base ref for squash boundary |
--branch NAME |
No | current branch | Branch to squash |
--message TEXT |
Cond. | N/A | Squash commit message |
--message-file PATH |
Cond. | N/A | Commit message file |
--push |
No | false |
Push rewritten history |
--remote NAME |
No | origin |
Remote target |
--yes |
No | false |
Required when --push |
--no-fetch |
No | false |
Skip pre-flight fetch |
--dry-run |
No | false |
Print actions only |
Scenarios
- Happy path: branch commits are squashed into one commit and kept local.
- Common operational path: squash feature branch before merge request finalization.
- Failure path: dirty worktree, invalid base, or no commits to squash.
- Recovery/rollback path: reset to generated backup branch.
Usage
git/squash-branch.sh --base origin/main --message "feat(api): consolidate billing endpoints"
git/squash-branch.sh --base release/2.1 --message-file .git/SQUASH_MSG
git/squash-branch.sh --base origin/main --message "fix(auth): simplify token flow" --push --yes
Behavior
- Main execution flow:
- validates refs and message inputs
- ensures clean working tree
- computes merge-base and commit span
- creates backup branch
- soft-resets to merge-base and creates single commit
- optionally force-pushes with lease
- Idempotency notes: non-idempotent due commit history rewrite.
- Side effects: rewrites branch history; creates backup branch; optional remote force update.
Output
- Standard output format: timestamped logs on stderr.
- Exit codes:
0success2argument/state validation failure- git command exit code for runtime failures
Failure Modes
- Common errors and likely causes:
- missing commit message input
- branch equals base
- rejected force push due lease mismatch/policy
- Recovery and rollback steps:
- restore from backup branch
- rebase/merge latest remote then retry push
- rerun with corrected message/ref values
Security Notes
- Secret handling: commit messages may contain sensitive data; validate before push.
- Least-privilege requirements: minimal repo permissions plus optional force-push rights.
- Audit/logging expectations: history rewrite events should be tracked in PR notes/review comments.
Testing
- Unit tests:
- mutual exclusivity (
--messagevs--message-file) - clean-tree and commit-count checks
- Integration tests:
- squash on feature branch and validate single commit output
- push path with
--force-with-lease - Manual verification:
- inspect
git log --oneline <base>..HEADand ensure one commit remains