Chapter 5.7 — Autosquash — fixup & squash automation☕ 14 min read

Autosquash — Fixup & Squash Automation

Mark karo, phir autosquash karo. Professional history bina manual mehnat ke.

01What is Autosquash

You commit feat: add login. Then you find a typo. You commit fix: typo in login. Then another small issue: fix: forgot semicolon. Before your PR, you interactive-rebase, change the fix commits to fixup, and they merge into the original commit.

This is the correct workflow. But it is tedious if you do it many times per day.

Every fix requires: git rebase -i, find the fix commit in the list, change pick to fixup, save the file, close the editor. Five steps per fix. If you have 5 fix commits, that is 25 manual steps.

There is a better way: mark commits as fixups WHEN you create them, then let Git auto-arrange them during rebase. No manual editing needed.

# The manual workflow (tedious)
git commit -m "feat: add login"
git commit -m "fix: typo in login"
git commit -m "fix: forgot semicolon"
# ... more commits ...

# Before PR:
git rebase -i HEAD~5
# Manually change:
# pick abc123 feat: add login
# fixup def567 fix: typo in login       ← manually changed
# fixup ghi890 fix: forgot semicolon    ← manually changed
# Save, close editor, Git squashes them

# This works but is slow when you have many fixes
02fixup! Prefix

git commit --fixup=<hash> creates a commit with a special message: fixup! original message

Git recognizes the fixup! prefix and knows this commit belongs to the original commit. When you later run git rebase -i --autosquash, Git automatically changes these to fixup actions in the rebase plan.

No need to manually edit the rebase todo list — Git does it for you.

--fixup does not change the original commit — it just marks the NEW commit with a special prefix. The original commit stays untouched until rebase runs.

# Original commit
echo "function login() {}" > auth.js
git add auth.js
git commit -m "feat: add login"
# Hash: abc1234

# Find a typo, create a fixup commit
echo "function login(username) {}" > auth.js
git add auth.js
git commit --fixup=abc1234
# Git creates: "fixup! feat: add login"

# Find another issue, another fixup
echo "// validate" >> auth.js
git add auth.js
git commit --fixup=abc1234
# Git creates: "fixup! feat: add login"

# Check the log
git log --oneline
# def5678 fixup! feat: add login
# ghi9012 fixup! feat: add login
# abc1234 feat: add login
# The "fixup!" prefix tells Git these belong to the original
💡 Pro Tip: Using --fixup is a habit that saves hours. Every time you make a small fix that belongs to a previous commit, use --fixup=<hash> instead of writing a manual commit message. Later, autosquash cleans them all up automatically. No more manual rebase editing!
03squash! Prefix

git rebase -i --autosquash opens the rebase editor with fixup/squash commits PRE-CONFIGURED.

All commits marked with fixup! are automatically set to fixup action. All commits marked with squash! are automatically set to squash action.

They are placed right after their target commit — no manual reordering needed. You just save and close the editor. Git handles the rest.

If you want to review the plan, the editor shows it before execution. You can still make changes if needed.

# History with fixup commits
git log --oneline
# def5678 fixup! feat: add login
# ghi9012 fixup! feat: add login
# abc1234 feat: add login

# Run autosquash
git rebase -i --autosquash HEAD~3

# Editor opens with PRE-CONFIGURED actions:
pick abc1234 feat: add login
fixup def5678 fixup! feat: add login
fixup ghi9012 fixup! feat: add login

# No manual editing needed! Just save and close.
# Result: 3 commits become 1 clean commit

# If you want to change fixup to squash (to edit message):
# Edit in the editor before saving:
pick abc1234 feat: add login
squash def5678 fixup! feat: add login  ← changed to squash
fixup ghi9012 fixup! feat: add login
04--autosquash Flag

git commit --squash=<hash> is like --fixup, but during rebase it uses squash instead of fixup.

This means: combine with the target commit AND let me edit the combined message.

Use --fixup when: the fix is minor (typo, formatting) and the original message is fine as-is.

Use --squash when: the fix is significant and you want to rewrite the combined commit message.

Both are auto-arranged by --autosquash. The only difference is the rebase action they trigger.

# Original commit
git commit -m "feat: add login"

# Minor fix — use fixup (discard message)
echo "function login(username) {}" > auth.js
git add auth.js
git commit --fixup=HEAD~1
# Will auto-fixup during rebase (no message editing)

# Significant fix — use squash (edit message)
echo "// Added validation and error handling" >> auth.js
git add auth.js
git commit --squash=HEAD~2
# Will auto-squash during rebase (opens editor for message)

# Autosquash rebase
git rebase -i --autosquash HEAD~3

# Editor shows:
pick abc1234 feat: add login
fixup def5678 fixup! feat: add login      # auto-set
squash ghi9012 squash! feat: add login     # auto-set

# Fixup merges silently, squash opens editor for message
05Real Workflow

The professional workflow: commit freely with fixup marks, then autosquash before PR.

Step 1: Make your feature commits normally.

Step 2: When you find issues, commit with --fixup=<original-hash>.

Step 3: Before PR, run git rebase -i --autosquash to clean up.

Step 4: Save and close the editor. All fixups are applied automatically.

Pro tip: Use GIT_SEQUENCE_EDITOR=true git rebase -i --autosquash to skip the editor entirely. This makes the autosquash 100% automatic — no editor opens at all.

# Complete professional workflow

# 1. Feature commits
git commit -m "feat: add authentication"
AUTH_HASH=$(git rev-parse HEAD)

git commit -m "feat: add dashboard"
DASH_HASH=$(git rev-parse HEAD)

# 2. Fix commits (mark with --fixup)
echo "fix" >> auth.js && git add . && git commit --fixup=$AUTH_HASH
echo "fix" >> dashboard.js && git add . && git commit --fixup=$DASH_HASH
echo "fix2" >> auth.js && git add . && git commit --fixup=$AUTH_HASH

# 3. Before PR: autosquash
git rebase -i --autosquash
# Editor shows all fixups pre-configured. Save and close.

# Result: 5 commits become 2 clean commits
# feat: add authentication (includes 2 fixes)
# feat: add dashboard (includes 1 fix)

# 4. Fully automatic (no editor):
GIT_SEQUENCE_EDITOR=true git rebase -i --autosquash
# All fixups applied automatically without opening editor!

# 5. Push
git push --force-with-lease origin feature
The autosquash workflow is the most efficient way to maintain clean commit history. Instead of interrupting your flow to do interactive rebases after every fix, you simply mark commits with --fixup and batch-process them all before creating the PR. Set up an alias: git config --global alias.autofixup "rebase -i --autosquash" to make it even faster.

Lo kar liya — Key Points:

  • ✅ git commit --fixup=<hash> creates a commit marked "fixup! original message" that autosquash will auto-merge
  • ✅ git commit --squash=<hash> creates a commit marked "squash! original message" that autosquash will merge with message editing
  • ✅ git rebase -i --autosquash automatically arranges fixup/squash commits next to their targets
  • ✅ Use --fixup for minor fixes (typos, formatting) where the original message is fine
  • ✅ Use --squash for significant fixes where you want to rewrite the combined commit message
  • ✅ GIT_SEQUENCE_EDITOR=true git rebase -i --autosquash skips the editor entirely for 100% automation
  • ✅ The workflow: commit freely with --fixup marks, then autosquash before PR for clean history
Course Search
Search across all chapters & stages
📖

Search the course

Type any topic — branching, stash, rebase, hooks — and jump straight to that chapter.

merge branchesgit stashundo commitrebase