Automating repeated conflict resolution with rerere Jump to heading
A long-lived branch rebased onto a fast-moving trunk hits the same conflict repeatedly: once per replayed commit during the rebase, again the next day after another git pull --rebase, and a third time when a colleague rebases the same branch. Resolving an identical conflict by hand each time is wasted effort and — worse — an invitation to resolve it inconsistently. Git’s rerere (“reuse recorded resolution”) subsystem records how you resolved a conflict and replays that resolution automatically the next time the same conflict appears. This page is a concrete recipe within Reusing Conflict Resolutions with rerere, which covers the mechanism and its place in a safe-merge toolkit.
When to use this approach Jump to heading
Turn on rerere when:
- You rebase feature branches onto
mainfrequently and keep re-resolving the same hunks, especially during multi-commit interactive rebases on shared branches. - A long-running integration branch merges from trunk on a schedule and the same structural conflict (a moved import, a renamed config key) recurs every cycle.
- You use “rebase, test, discover a problem,
git rebase --abort, retry” loops and want the second attempt to skip the conflicts you already solved. - Your team wants conflict resolutions to be consistent across engineers rather than each person guessing at the same merge.
This recipe is not the right fit if the “conflict” is really a semantic decision that should differ each time it appears — rerere assumes an identical textual conflict deserves an identical resolution, which is exactly the assumption that makes a silent wrong replay dangerous.
The diagram below shows the record-once, replay-many flow that rerere implements.
Step-by-step recipe Jump to heading
Step 1 — Enable rerere and autoUpdate Jump to heading
rerere.enabled turns on recording and replay. rerere.autoUpdate additionally stages the replayed resolution so a rebase can continue without a manual git add. Set both globally so every repository benefits:
# Record and replay resolutions everywhere
git config --global rerere.enabled true
# Auto-stage a replayed resolution instead of leaving it unstaged
git config --global rerere.autoUpdate true Verify both flags resolved to true:
# Each command should print: true
git config --get rerere.enabled
git config --get rerere.autoUpdate Enabling rerere.enabled also creates the .git/rr-cache directory in each repo the first time a conflict is recorded — no manual setup is needed.
Step 2 — Resolve the conflict once during a rebase Jump to heading
Start the operation that produces the conflict. During a long rebase, Git stops at the first conflicting commit:
# Replay this feature branch onto the updated trunk
git rebase main
# Git halts: "CONFLICT (content): Merge conflict in src/config.ts" The moment the conflict appears, rerere records the pre-image — the raw conflict, keyed by its hash. Resolve the file exactly as you intend it, then confirm and continue:
# Edit src/config.ts to the correct merged content, then:
git add src/config.ts
git rebase --continue Verify the file no longer contains conflict markers before you stage it:
# Prints nothing when the file is fully resolved
grep -nE '^(<<<<<<<|=======|>>>>>>>)' src/config.ts Step 3 — Confirm the resolution was recorded Jump to heading
rerere captured the post-image (your resolution) when you ran git add on the resolved file. Check that it is now stored:
# Lists conflict paths for which a resolution has been recorded
git rerere status You can also see the recorded cache entry on disk. Each conflict hash gets its own directory holding preimage and postimage files:
# One subdirectory per recorded conflict hash
ls -1 .git/rr-cache/ If git rerere status prints the path you just resolved, the resolution is banked and ready to replay.
Step 4 — Watch the resolution auto-replay on the next conflict Jump to heading
The next time the identical conflict appears — a later commit in the same rebase, a re-run after git rebase --abort, or tomorrow’s git pull --rebase — rerere recognizes the hash and replays your resolution:
# Re-run the rebase after aborting, or pull again later
git rebase main
# Git reports: "Resolved 'src/config.ts' using previous resolution." With rerere.autoUpdate on, the file is already staged. Confirm the replay actually produced the content you expect before continuing:
# Review what rerere staged — do NOT trust it blindly
git diff --cached src/config.ts
# If correct, continue the rebase
git rebase --continue SAFETY WARNING: With
rerere.autoUpdateenabled, a previously recorded wrong resolution is replayed and staged silently — Git prints one “using previous resolution” line and moves on, so a bad merge can slip into a commit unnoticed. Always rungit diff --cachedon the auto-resolved path beforegit rebase --continue, and if the replay is wrong, drop it withgit rerere forget <path>and resolve by hand.
Step 5 — Share the rr-cache across the team Jump to heading
By default .git/rr-cache is local and never pushed. To let a whole team reuse the same resolutions for a recurring integration conflict, sync the cache directory out of band — a shared location plus a symlink is the simplest reliable pattern:
# One-time: move the cache to a shared, synced location and link it back
mkdir -p /shared/team-rr-cache
mv .git/rr-cache/* /shared/team-rr-cache/ 2>/dev/null || true
rm -rf .git/rr-cache
ln -s /shared/team-rr-cache .git/rr-cache For teams without a shared filesystem, commit resolutions from a designated “integrator” and distribute the rr-cache entries as a tarball, or use a dedicated sync tool. Verify the link resolves and Git still reads it:
# Should show the symlink target and list shared hash directories
ls -ld .git/rr-cache && ls -1 .git/rr-cache/ Because every entry is keyed by a content hash, merging two caches never collides destructively — identical conflicts map to identical directories, and unrelated ones coexist.
Step 6 — Inspect state and forget a bad resolution Jump to heading
Two commands give you visibility into what rerere is holding. git rerere status lists paths with an active recorded resolution during a conflict; git rerere diff shows the difference between the recorded conflict and its stored resolution:
# Which conflicted paths have a recorded resolution?
git rerere status
# What resolution will be applied for the current conflict?
git rerere diff When a resolution is wrong — or you resolved a conflict incorrectly and it is now poisoning every replay — remove it so the conflict resurfaces for a clean redo:
# Drop the recorded resolution for this path; the conflict returns
git rerere forget src/config.ts Verify the entry is gone and then re-resolve the conflict correctly, which records a fresh resolution:
# The path should no longer appear as auto-resolved
git rerere status
# Re-edit the file, then re-stage to record the corrected resolution
git add src/config.ts SAFETY WARNING:
git rerere forget <path>only drops the recorded resolution — it does not revert any commit that already captured the bad merge. If a wrong auto-replay was already committed during a rebase, fix history separately (for example with an interactive rebase on the shared branch) after forgetting the cache entry.
Validation checklist Jump to heading
Before relying on rerere for real conflict work, confirm each item:
Frequently asked questions Jump to heading
Does rerere change my commits or only my working tree? Jump to heading
rerere only stages resolved file contents in your working tree and index; it never creates or amends commits on its own. With rerere.autoUpdate on, it applies the recorded resolution and stages the file, but you still complete the merge or rebase step yourself with git rebase --continue or git commit. Without autoUpdate, it writes the resolution into the working file but leaves it unstaged so you can review before running git add.
How does rerere decide two conflicts are the same? Jump to heading
rerere computes a normalized hash of the conflict itself — the pre-image formed by the conflicting hunks and their surrounding context, with branch-specific noise stripped out. The recorded resolution is keyed by that hash under .git/rr-cache. If the same conflict shape reappears, even in a different file path or a later rebase replay, the hashes match and the stored resolution is reused. This is also why a resolution recorded on one machine can be shared: the key is derived purely from conflict content.
Can rerere apply a wrong resolution without telling me? Jump to heading
Yes. If a conflict hashes identically to one you previously resolved incorrectly, rerere replays the bad resolution and — with autoUpdate — stages it silently, printing only a one-line “using previous resolution” notice. Always review the auto-resolved diff with git diff --cached before continuing, and run git rerere forget <path> to drop the recorded resolution so the next occurrence conflicts normally and you can redo it correctly.
Related Jump to heading
- Reusing Conflict Resolutions with rerere — the parent page covering the rerere mechanism, its cache model, and where automated conflict reuse fits in a safe-merge strategy.
- Safe Git Rebase -i for Shared Branches — the interactive-rebase workflow where rerere pays off most, and where you repair history if a bad resolution was committed.
- Conflict Resolution & Safe Merge Operations — the section overview tying together merge fundamentals, cherry-picking, rebase workflows, and conflict automation.