`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.

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 trueFrom 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: 3Every 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: 3Cherry-picking that hotfix onto release-2.1 conflicts, because both sides changed log_level:
git cherry-pick fc43863Auto-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: 3Recorded 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: 3git add config.yml
git cherry-pick --continueRecorded resolution for 'config.yml'.
[release-2.1 5d3ca8e] hotfix: raise timeout and quiet default loggingRecorded 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 fc43863Auto-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: 3git add config.yml
git cherry-pick --continueSame 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
mainmoves — 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.autoUpdateskips the reminder step. By default git still leaves the file staged as unmerged so you have to rungit addyourself, as a last chance to notice something's off. Settinggit config rerere.autoUpdate truestages 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.