/git-squash - Squash Commits
Combine multiple commits into fewer, cleaner commits non-interactively.
Usage
bash
/git-squash 3 # Squash last 3 commits into 1 /git-squash --since main # Squash all commits since main /git-squash --all # Squash all commits on branch into 1 /git-squash --preview # Show what would be squashed
When to Use
- •Before PR: Clean up WIP commits into logical units
- •After review: Squash fixup commits
- •Messy history: Combine related small commits
- •Before merge: Create clean, meaningful commits
Workflow
Step 1: Determine Commits to Squash
bash
# Last N commits SQUASH_COUNT=3 # Or commits since branching from main SQUASH_COUNT=$(git rev-list --count main..HEAD) # Show commits that will be squashed echo "Commits to squash:" git log --oneline -n "$SQUASH_COUNT"
Step 2: Pre-flight Checks
bash
# Check for uncommitted changes
if ! git diff --quiet || ! git diff --cached --quiet; then
echo "Commit or stash your changes first."
exit 1
fi
# Ensure we have commits to squash
if [ "$SQUASH_COUNT" -lt 2 ]; then
echo "Need at least 2 commits to squash."
exit 1
fi
Step 3: Create Squash Commit Message
bash
# Gather all commit messages MESSAGES=$(git log --format="%s" -n "$SQUASH_COUNT" | tac) # Generate combined message BRANCH=$(git branch --show-current) echo "Squashed commits from $BRANCH:" echo "" echo "$MESSAGES"
Step 4: Execute Squash (Non-Interactive)
bash
# Soft reset to keep changes staged git reset --soft HEAD~"$SQUASH_COUNT" # Create new commit with combined message git commit -m "Combined message here"
Step 5: Report Result
Show the squash result and next steps.
Output Format
Preview Mode
code
Would squash 5 commits: abc1234 WIP: starting feature def5678 More work on feature ghi9012 Fix typo jkl3456 Actually fix the bug mno7890 Final touches Combined changes: 4 files changed, 123 insertions(+), 45 deletions(-) src/components/Feature.tsx src/hooks/useFeature.ts src/styles/feature.css tests/feature.test.ts Run without --preview to execute.
Successful Squash
code
Squashed 5 commits into 1: Before: abc1234 WIP: starting feature def5678 More work on feature ghi9012 Fix typo jkl3456 Actually fix the bug mno7890 Final touches After: xyz7890 Add feature component with styles and tests Files in squashed commit: src/components/Feature.tsx src/hooks/useFeature.ts src/styles/feature.css tests/feature.test.ts Note: History was rewritten. If already pushed: git push --force-with-lease
Squash All Since Main
code
Squashing all commits since main (7 commits)... Before: (7 commits with various WIP messages) After: feat: Add complete dark mode implementation - Theme toggle component - System theme detection - Persistent preference storage - Updated color palette Ready for PR! Run: /git-push --force-with-lease /commit-push-pr
Commit Message Strategies
Option 1: Single Summary
code
feat: Add user authentication Implements login, logout, and session management.
Option 2: Bullet Points (for larger squashes)
code
feat: Add user authentication - Add login form component - Implement session management - Add logout functionality - Add remember me option - Add password reset flow
Option 3: Preserve Original Messages
code
feat: Add user authentication Squashed commits: - Add login form component - Wire up authentication API - Add session storage - Fix validation bugs - Add tests
Interactive Alternative
For more control, use interactive rebase:
bash
# Interactive rebase for last 5 commits git rebase -i HEAD~5 # In editor, change 'pick' to 'squash' (or 's') for commits to combine # Then edit the combined commit message
Note: Claude cannot run interactive commands, but can guide you through them.
Safety Notes
- •Only squash unpushed commits: Or commits on your personal branch
- •Never squash shared history: Others may have based work on it
- •Force push needed: After squashing pushed commits
- •Backup first: If unsure, create a backup branch
bash
# Create backup before squashing git branch backup-before-squash
Integration
- •Use before
/git-pushto clean up history - •Use before
/commit-push-prfor clean PRs - •Use
/git-push --force-with-leaseafter squashing pushed commits - •Consider PR squash-merge instead for simple cases