How do git commit --fixup and git rebase -i --autosquash work together?
answer
- two steps, not one
- the subject line carries the instruction
- the rebase reorders before you see the todo
- one prefix keeps messages, one drops them
- rebase.autoSquash makes it the default
basics
~20 sgit commit --fixup=<commit> records a normal commit whose subject is "fixup! " plus the target's subject. A later git rebase -i --autosquash reads those markers, moves each fixup commit next to its target, and marks it to be folded in.
solid answer
~50 s`git commit --fixup=<commit>` commits your staged correction immediately, but writes a machine-readable subject: `fixup! ` followed by the subject line of the commit it belongs to. Nothing is rewritten yet, so you can keep working and push nothing until you are ready. When you run `git rebase -i --autosquash <base>`, Git pre-arranges the todo list: each `fixup!` commit is reordered directly after its target and its action is set to `fixup`, which merges its changes into the target and **discards** its message. `git commit --squash=<commit>` is the sibling that writes `squash! `; those get the `squash` action, which folds the changes in but combines both messages in an editor. Set `rebase.autoSquash = true` to get the behaviour without typing the flag. The result is a clean series where review fixes disappear into the commits they fix.
code
bash · 4 linesgit add src/Parser.kt
git commit --fixup=HEAD~2
git log --oneline -1
git rebase -i --autosquash HEAD~4go deeper
Know that --fixup makes an ordinary commit with a special subject, and that a later interactive rebase with --autosquash is what actually folds it in. Nothing is rewritten at fixup time.
Explain the two-step mechanism, how the todo list is reordered before you see it, and the fixup-versus-squash difference in what happens to the messages.
Show why batching corrections beats amending or rebasing after every review comment: one conflict-resolution pass, no half-finished rebase state, and a deliberate moment when history is rewritten.
Argue when a curated commit series is worth the rewrite cost versus letting a merge carry the raw history, and what that implies for review and bisect quality across teams.
## The problem this solves You have a branch of five commits. A reviewer points out a bug in the second one. You can amend only the tip, so your options are: add a "fix review comment" commit that pollutes the history forever, or start an interactive rebase, stop at the second commit, edit, and continue — which interrupts your work right now and risks conflicts you would rather handle once. `--fixup` gives you a third option: record the correction now with a marker, and let a single rebase later put it in the right place. ## Step one: record the marker commit Stage the correction and run `git commit --fixup=<commit>`, where `<commit>` names the commit to be fixed (a SHA, `HEAD~2`, a tag — any revision). Git creates an ordinary commit; the only special thing about it is the subject, which is literally `fixup! ` followed by the target commit's subject line. No editor opens. Nothing in history is rewritten. If you run `git log --oneline` you see the fixup sitting at the tip like any other commit. `git commit --squash=<commit>` is the same mechanism with the prefix `squash! `. Recent Git also accepts `--fixup=amend:<commit>` and `--fixup=reword:<commit>`, which produce `amend!` commits that additionally replace the target's message — useful when the fix includes rewording. ## Step two: let the rebase place it `git rebase -i --autosquash <base>` opens the todo list, but before you see it Git has rewritten it: every commit whose subject starts with `fixup!` or `squash!` has been moved to sit immediately after the commit whose subject it names, and its action word changed from `pick` to `fixup` or `squash`. You review the plan and save. During the replay: - `fixup` applies the commit's changes on top of the preceding one and keeps the preceding commit's message. The fixup message vanishes — that is the point. - `squash` applies the changes and opens an editor with both messages concatenated so you can write a combined message. All the rewritten commits get new SHAs, because the trees and parents change; that is inherent to rebase. ## Choosing the base `<base>` must be an ancestor of everything you want reordered, and it should be a commit you have not published. `git rebase -i --autosquash origin/main` is the common shape for a feature branch: it replays everything you added since the upstream tip. `HEAD~6` works when you can count. ## Configuration `rebase.autoSquash = true` makes the flag the default for interactive rebase; `--no-autosquash` opts out for a single run. `rebase.autoStash = true` is an unrelated but frequently paired setting that stashes and restores a dirty working tree around the rebase. ## How matching works Autosquash matches on the **subject text** after the prefix. That has two consequences worth knowing. If you later reword the target commit's subject, its fixup no longer matches and will just be picked as an ordinary commit — you would fix the plan by hand in the editor. And if two commits share an identical subject, the association is ambiguous; Git cannot know which one you meant, which is a practical argument for distinct subjects. ## Why not just amend or rebase immediately Amend only reaches HEAD. An immediate interactive rebase forces you to resolve any conflicts right now and repeatedly, once per correction. Batching corrections as fixups means one rebase, one conflict resolution pass, and a working tree that is never mid-rebase while you are still thinking about the code. It also keeps every correction as a separate reviewable step until the moment you deliberately collapse them. ## The caveat The final rebase rewrites history. That is safe for a branch only you have, and a coordination problem for a branch others have built on — the fixup workflow does not change that calculus, it only delays the rewrite to a single moment you choose. ## Interview framing Name both halves — the marker commit and the rebase that consumes it — and the difference between `fixup` (drops the message) and `squash` (merges messages). Candidates who only know `--fixup` usually cannot explain why the marker subject matters.
- What is the difference between --fixup and --squash?Both create a marker commit that autosquash will fold into a target. `--fixup` writes a `fixup!` subject and the rebase discards that message entirely, keeping the target's. `--squash` writes a `squash!` subject and the rebase concatenates both messages in an editor so you can write a combined one. Use fixup for pure corrections, squash when the folded work deserves a mention in the message.
- What happens if you reword the target commit's subject before running the autosquash rebase?The association breaks. Autosquash matches the text after the `fixup!` prefix against commit subjects, so a reworded target no longer matches and the fixup commit is simply picked as an ordinary commit. You would fix it by editing the todo list by hand — move the line and change `pick` to `fixup` yourself.
- Do fixup commits need special handling if you push the branch before rebasing?They are normal commits, so pushing them works. The problem comes later: collapsing them rewrites the branch, so the published tip no longer matches. Either keep the fixups local until you collapse them, or accept that the branch will need a force update once you do.
saying these in an interview costs you the question
- Thinks --fixup rewrites history by itself
- Believes the fixup commit's message survives the rebase
- Confuses --fixup with --amend
- Thinks autosquash works without a rebase
- Assumes the marker matches by SHA rather than subject