If you maintain patch series (for kernel upstream, for example), you’ve probably done this dance many times:

git rebase -i <base>
# change "pick" to "edit" on the target commit
# make your fix, git add, git commit --amend
# git rebase --continue

It works, but it’s tedious — especially when you have multiple fixes targeting different commits. There’s a better way.

The Workflow

1. Make your fix, then --fixup

After editing the file, instead of starting a rebase right away:

1
2
git add -u
git commit --fixup=<target-commit>

This creates a commit with a special message prefix:

fixup! <original commit message>

It’s just a normal commit with a marker. You can create multiple fixup commits targeting different commits before rebasing.

2. Autosquash them all at once

1
git rebase -i --autosquash <base>

Git sees the fixup! prefixes, automatically reorders the TODO list, and marks them as fixup. You don’t touch anything — just save and quit the editor.

If you trust the automation and don’t need to review the TODO:

1
GIT_SEQUENCE_EDITOR=true git rebase -i --autosquash <base>

GIT_SEQUENCE_EDITOR=true skips the editor entirely.

Skip the Hash Lookup with :/

The annoying part of --fixup=<hash> is finding the hash. You can use a regex search instead:

1
git commit --fixup=:/keyword

:/ tells git to search commit messages. It finds the most recent commit whose message matches. Examples:

1
2
3
git commit --fixup=:/fixed-sample-rate
git commit --fixup=:/dt-bindings.*K3
git commit --fixup=:/FIFO trigger

As long as the match is unambiguous, it works. If nothing matches or multiple commits match, git errors out — no silent mistakes.

A Real Example

Say you have a 7-patch series and discover a bug in patch 4 (ASoC: dt-bindings: add SpacemiT K3 SoC compatible) and patch 7 (ASoC: spacemit: add K3 SoC support with additional clocks).

Fix the YAML file:

1
2
git add Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml
git commit --fixup=:/dt-bindings.*K3

Fix the C file:

1
2
git add sound/soc/spacemit/k1_i2s.c
git commit --fixup=:/K3 SoC support

Now your log looks like:

fixup! ASoC: spacemit: add K3 SoC support with additional clocks
fixup! ASoC: dt-bindings: add SpacemiT K3 SoC compatible
ASoC: spacemit: add K3 SoC support with additional clocks
ASoC: spacemit: add fixed-sample-rate constraint support
ASoC: dt-bindings: add fixed-sample-rate property for SpacemiT K1/K3
ASoC: dt-bindings: add SpacemiT K3 SoC compatible
...

One command to fold them in:

1
GIT_SEQUENCE_EDITOR=true git rebase -i --autosquash <base>~1

Done. Both fixups are absorbed into their target commits. Clean history, no manual editing.

--fixup vs --squash

--fixup--squash
Prefixfixup!squash!
During rebaseSilently merges, keeps original messageOpens editor to combine messages
Use caseBug fixes, silent correctionsAdding context to commit messages

For patch series maintenance, --fixup is almost always what you want.

Summary

Old wayNew way
git rebase -i, manually change pickeditgit commit --fixup=:/keyword
Stop at commit, amend, continuegit rebase -i --autosquash
One fix at a timeBatch multiple fixups, rebase once