letting Git resolve recurring merge conflicts automatically
Anyone who regularly rebases a long-lived feature branch onto main knows the pattern: the same conflict in the same file keeps coming back on every rebase. git rerere records the resolution once it has been made manually and reapplies it automatically the next time the exact same conflict shows up, with no external tool required.
Table of Contents
- 1. What git rerere does and what it was built for
- 2. Enabling rerere and understanding the cache
- 3. The workflow behind a recurring conflict
- 4. Typical use cases: long feature branches and cherry-pick chains
- 5. Maintaining the rerere cache: forget, diff, and checking status
- 6. Risks: automatically reapplying a resolution that was wrong
- 7. rerere in a team: why the cache usually stays local
- 8. Pre-populating the cache with a training script
- 9. How rerere differs from merge strategies and custom drivers
- 10. Summary
- 11. FAQ
1. What git rerere does and what it was built for
Rerere stands for reuse recorded resolution, meaning the reuse of a conflict resolution that has already been recorded. Once the feature is enabled, Git records the state before and after every manually resolved merge conflict. If a conflict with the exact same before state shows up again later, Git applies the stored resolution automatically, with no manual intervention required.
The tool kicks in for every operation that can produce a conflict, meaning git merge, git rebase, and git cherry-pick alike. It becomes especially valuable for repeated operations against the same underlying data, for instance when a feature branch needs to be rebased again after every force push to main and keeps hitting the same spot in a configuration file every time.
2. Enabling rerere and understanding the cache
By default rerere is disabled in most Git installations and has to be turned on explicitly, either globally for every repository or for a single project. Once active, Git creates its internal store under .git/rr-cache, a purely local directory that is not part of the versioned project files.
An additional option is rerere.autoupdate: when set, Git immediately runs an implicit git add on the affected file right after an automatically detected conflict resolution, so no manual step is needed to mark that resolution as staged.
# Enable rerere globally for every repository
git config --global rerere.enabled true
# Also stage automatically detected resolutions right away
git config --global rerere.autoupdate true
3. The workflow behind a recurring conflict
The first time a conflict occurs, everything plays out as usual: Git marks the affected spots with the familiar conflict markers, the conflicting lines get cleaned up manually, the file is staged with git add, and the merge or rebase continues. Behind the scenes, rerere has already recorded the before state and the chosen resolution in the cache at that exact moment.
If the exact same conflict content shows up again later, for instance because the same feature branch gets rebased again after another commit lands on main, Git recognizes the already known conflict automatically, applies the stored resolution, and marks the affected spot as resolved directly, without the conflict markers ever becoming visible.
# Git prints a hint after automatically resolving a known conflict
git rebase main
# Resolved 'config/app.yaml' using previous resolution.
4. Typical use cases: long feature branches and cherry-pick chains
The classic use case is a feature branch developed over several weeks in parallel with main and rebased onto it repeatedly. When the same generated file or the same central configuration file collides every single time, rerere saves any manual repetition of that same resolution from the second occurrence onward.
A second common scenario is a chain of cherry-picks across several release branches, where the same hotfix commits need to be applied to slightly different branch states. Once the first cherry-pick produces the matching resolution, rerere can carry that same resolution over to the following branches automatically.
5. Maintaining the rerere cache: forget, diff, and checking status
For visibility during an active conflict, git rerere status lists the paths where a stored resolution was found or used, while git rerere diff shows exactly which changes rerere is about to apply automatically before they are actually committed to.
If an automatic resolution was applied incorrectly, git rerere forget with the affected path removes that specific record from the cache, so the next occurrence of the conflict requires a manual decision again. Old entries that have not been needed in a while get cleaned up automatically by git rerere gc after configurable time windows for both resolved and unresolved conflicts.
# Inspect current rerere status during an active conflict
git rerere status
git rerere diff
# Discard a resolution that was learned incorrectly for a path
git rerere forget config/app.yaml
6. Risks: automatically reapplying a resolution that was wrong
The biggest weakness of rerere is also its biggest strength: it remembers exactly what was decided once, regardless of whether that decision was actually correct. If the first resolution was flawed, Git silently reapplies that same flawed resolution the next time the identical conflict occurs, without asking again.
Especially with security relevant code or complex business logic, it pays off to double check with git diff what was actually applied after every automatically resolved conflict, instead of trusting the automation blindly. rerere does not replace code review, it only speeds up the mechanical repetition of a decision that has already been made once.
7. rerere in a team: why the cache usually stays local
The .git/rr-cache directory sits outside the normal project files and is not versioned with commits by default, meaning every developer builds up their own, independent local cache. That is sensible in most cases anyway, since conflict resolutions often depend on individual local branch states that vary between team members.
In rare cases, for instance a very large team that keeps independently resolving the same known conflict in a generated file, the cache can technically be shared through a custom distribution script, but in practice that stays the exception rather than a standard recommendation.
8. Pre-populating the cache with a training script
The contrib directory of the Git source tree ships a script called rerere-train.sh, which walks through a repository's entire existing merge history, replays every historical merge commit, and feeds the resulting conflict resolutions into the local rerere cache.
That is particularly useful right after freshly cloning a repository whose team already deals with known, recurring conflicts: instead of resolving each of those conflicts manually all over again, the training script pre-fills the cache so rerere can already kick in on the very first rebase of your own.
# Train rerere on the existing merge history once
./rerere-train.sh $(git rev-list --all --merges)
9. How rerere differs from merge strategies and custom drivers
rerere does not replace content-level merge strategies such as a merge=union driver defined in .gitattributes, which decides upfront for certain file types how changes should be merged automatically. A driver like that applies a general rule before a conflict even arises.
rerere, by contrast, only kicks in after a conflict has actually occurred and been resolved manually once, and it then repeats exactly that specific, already made decision. The two mechanisms complement each other well: a merge driver covers predictable, generic cases, rerere handles the individual, recurring conflicts that cannot be solved with a blanket rule.
| Trait | git rerere | merge=union driver | Manual repetition |
|---|---|---|---|
| Applies before or after the conflict | After the first manual resolution | Before the conflict even arises | Every single time it occurs |
| Where the resolution is stored | Local cache under .git/rr-cache | Rule in .gitattributes, versioned | Nowhere, redone every time |
| Fits individual conflicts | Yes, exact before and after states | No, only generic rules | Yes, but time consuming |
| Degree of automation | High, automatic after the first time | High, but rule based only | None |
Mironsoft
Git workflows, branching strategies, and CI hooks
Chaotic Git history and unclear branching rules across the team?
We set up clean Git workflows, clarify branching strategies for the team, and automate quality checks via Git hooks and CI pipelines so the history stays traceable.
Workflow Audit
Review the existing branching strategy and merge practice for weak spots.
Hook Automation
Set up pre-commit and pre-push hooks for linting, tests, and commit conventions.
Team Training
Teach rebase, cherry-pick, and conflict resolution hands-on across the team.
10. Summary
Git Rerere
Core idea
git rerere remembers a manually found conflict resolution and reapplies it automatically the next time an identical conflict occurs.
Activation
git config rerere.enabled true turns the mechanism on, the cache lives locally under .git/rr-cache.
Typical use
Long-lived feature branches with repeated rebases and cherry-pick chains across several release branches.
Key rule
Still check automatically applied resolutions with git diff, rerere also repeats a decision that was wrong in the first place.