SeriesPart 4 of 8 // Git Quick Hits
gitWriting
Aug 31, 2026
3 min read
git-quick-hits

`git rerere`: Stop Resolving the Same Conflict Twice

Backporting one hotfix onto three release branches means resolving the same textual conflict three times by hand — unless you turn on git rerere and let it replay the fix after the first one.

Three parallel branch lines each hitting an identical conflict marker, with a stamp pressing the same resolved patch onto all three at once.

A hotfix needs to go out on release-2.1, release-2.2, and release-2.3 at once. Each release branch carries the same small local override — a config line that never matches whatever the hotfix touches on main — so cherry-picking the fix onto the first branch produces a conflict. You resolve it. Then you cherry-pick onto the second branch and hit the identical conflict, word for word, and resolve it the identical way. Then a third time.

git rerere — "reuse recorded resolution" — notices when a conflict looks exactly like one you've already fixed, and applies your old fix automatically.

Turn it on

rerere is off by default and scoped per repository:

git config rerere.enabled true

From this point on, every conflict resolution gets cached, keyed by the exact content of the conflicting hunks.

The setup: one override, three branches

A config file with a line each release branch overrides locally, for its own reasons:

# config.yml on main
timeout: 30
log_level: info
retries: 3

Every release branch sets log_level: debug instead, committed once on each branch. Then a hotfix lands on main that happens to touch both timeout and log_level in the same commit:

# config.yml on main, after the hotfix
timeout: 45
log_level: warn
retries: 3

Cherry-picking that hotfix onto release-2.1 conflicts, because both sides changed log_level:

git cherry-pick fc43863
Auto-merging config.yml
CONFLICT (content): Merge conflict in config.yml
Recorded preimage for 'config.yml'
<<<<<<< HEAD
timeout: 30
log_level: debug
=======
timeout: 45
log_level: warn
>>>>>>> fc43863 (hotfix: raise timeout and quiet default logging)
retries: 3

Recorded preimage for 'config.yml' — that's rerere quietly noting what the unresolved conflict looked like. Resolve it by hand, the way you always would: take the hotfix's timeout bump, keep the release branch's debug logging.

timeout: 45
log_level: debug
retries: 3
git add config.yml
git cherry-pick --continue
Recorded resolution for 'config.yml'.
[release-2.1 5d3ca8e] hotfix: raise timeout and quiet default logging

Recorded resolution for 'config.yml' — now rerere has both the shape of the conflict and the fix you applied to it.

The payoff: branches two and three

Cherry-pick the exact same hotfix onto release-2.2:

git cherry-pick fc43863
Auto-merging config.yml
CONFLICT (content): Merge conflict in config.yml
Resolved 'config.yml' using previous resolution.

Resolved 'config.yml' using previous resolution. Git still reports a conflict — it always will, so you get a chance to double-check — but the file already contains the correct merged content, no editing required:

cat config.yml
# timeout: 45
# log_level: debug
# retries: 3
git add config.yml
git cherry-pick --continue

Same result on release-2.3. Three branches, one manual resolution instead of three.

What it's actually for

Rerere earns its keep on any workflow where the same conflict shape shows up more than once:

  • Backporting one fix to several long-lived release branches, exactly as above.
  • Rebasing a long-running feature branch repeatedly as main moves — if your branch always collides with the same lines, you only resolve it for real once.
  • Re-doing a merge you aborted to think it over. The resolution you'd have made is waiting for you when you come back.

It won't help with a conflict that's genuinely new each time, and it isn't shared with your team by default — the cache lives in .git/rr-cache, local to your clone. Some teams commit a shared rerere cache for exactly this reason, but that's a bigger decision than turning the config flag on.

A couple of sharp edges

Rerere matches on the exact text of a conflict, not on intent, so it's worth knowing where that breaks down:

  • It replays the resolution, not the reasoning. If the right fix for a given conflict actually depends on what else changed nearby — not just the two colliding lines — rerere will still confidently reapply the old text. Skim the diff after a "using previous resolution" before you trust it blindly on something unfamiliar.
  • rerere.autoUpdate skips the reminder step. By default git still leaves the file staged as unmerged so you have to run git add yourself, as a last chance to notice something's off. Setting git config rerere.autoUpdate true stages the replayed resolution automatically — convenient once you trust the cache, risky before you do.
  • git rerere forget <path> clears a specific cached resolution if you ever recorded a bad one. There's no undo beyond that; the wrong fix gets replayed on every future match until you forget it.

git config rerere.enabled true costs nothing and never resolves anything incorrectly on its own — it only ever replays a fix you already made. Turn it on before the next release backport, not during it.

Series contents

01
Automating Regression Hunts with `git bisect run`
Read
02
Parallel Branches Without Stashing: `git worktree`
Read
03
The Undo Button Nobody Uses: `git reflog`
Read
04
`git rerere`: Stop Resolving the Same Conflict Twice
Current
05
`.gitignore` vs `.git/info/exclude` vs Global Excludes
Coming soon // Sep 7, 2026
06
Shipping a Repo as One File with `git bundle`
Coming soon // Sep 14, 2026
07
Attaching Build Metadata with `git notes`
Coming soon // Sep 21, 2026
08
Why Shallow Clones Break Your Changelog
Coming soon // Sep 28, 2026