Training rerere from existing merge history Jump to heading

rerere — reuse recorded resolution — only remembers conflicts it saw being resolved while it was enabled. Turn it on today and its cache is empty, even though your repository’s history contains hundreds of merge commits whose resolutions are exactly what you would want it to reuse. Git ships a small script, rerere-train.sh, that fixes this. It walks past merge commits, re-performs each merge to reproduce the conflicts, and records the resolution the merge commit actually contains. After training, rebasing a long-lived branch or re-running an integration merge can resolve familiar conflicts automatically on the first attempt. This page shows how to run it, scope it, and check what it learned, within rerere conflict automation.

When to use this approach Jump to heading

  • You are enabling rerere on a repository with a long history of merges between the same branches.
  • You need to rebase or re-merge a long-lived branch whose previous merges involved many conflict resolutions.
  • A colleague resolved a difficult set of conflicts in a merge commit, and you want your rerere to know them too — a simpler alternative to sharing rerere resolutions across a team.
  • rerere is already familiar; the basics are in automating repeated conflict resolution with rerere.

Step 1 — Find the training script Jump to heading

rerere-train.sh lives in Git’s contrib directory. Packages install it in different places, and some do not install it at all; it is a short shell script that you can also fetch from Git’s source for your version.

find / -name 'rerere-train.sh' -path '*contrib*' 2>/dev/null | head -1
# Typical locations:
#   /usr/share/doc/git/contrib/rerere-train.sh
#   /usr/share/git-core/contrib/rerere-train.sh
cp "$(find / -name rerere-train.sh 2>/dev/null | head -1)" ~/bin/git-rerere-train
chmod +x ~/bin/git-rerere-train

Step 2 — Enable rerere and train on a range of history Jump to heading

Training replays merges, so give it a range — usually the history of the branch whose merges you want to learn from. It accepts any revision arguments git rev-list does.

git config rerere.enabled true
# Learn from every merge on main in the last year
git rerere-train --since=1.year main
# Or from merges of one long-lived branch into main
git rerere-train ^main~500 main
What rerere-train does for each mergeFor every merge commit in the range, the script checks out the first parent, merges the second parent to reproduce the conflicts, then checks out the merge commit's own result for the conflicted files and records it as the resolution, before resetting and moving on.Merge commitfrom the rangeRe-mergeparent 1 + parent 2Conflicts?recorded preimagesTake resultfrom merge commitRecordrr-cache entrythe merge commit's tree is treated as the correct answer for each conflict it contains

The script checks out commits in your working tree, so run it in a clean worktree, not the one you are working in.

git worktree add --detach ../rerere-training
cd ../rerere-training && git rerere-train --since=1.year main
cd - && git worktree remove ../rerere-training

The rr-cache directory is shared between worktrees of the same repository, so resolutions learned in the training worktree are available everywhere.

Step 3 — Check what was learned Jump to heading

The cache lives in .git/rr-cache, one directory per conflict. Counting entries before and after training shows how much was learned; inspecting one confirms it looks right.

ls "$(git rev-parse --git-common-dir)/rr-cache" | wc -l
d=$(ls -t "$(git rev-parse --git-common-dir)/rr-cache" | head -1)
ls "$(git rev-parse --git-common-dir)/rr-cache/$d"            # preimage, postimage
diff "$(git rev-parse --git-common-dir)/rr-cache/$d/preimage" "$(git rev-parse --git-common-dir)/rr-cache/$d/postimage" | head -20

The fuller guide to reading the cache is inspecting the rerere cache.

Conflicts auto-resolved after trainingAn illustrative re-merge of a long-lived branch with forty conflict hunks. With an empty cache, rerere resolves none. After training on a year of merges, most recurring hunks resolve automatically, leaving only genuinely new conflicts to handle by hand.conflict hunks in one re-merge (illustrative)total hunks40auto, empty cache0auto, after training31left for you9training pays off on branches that keep meeting the same conflicts

Step 4 — Scope training to avoid learning bad resolutions Jump to heading

A merge commit’s tree is not always a pure conflict resolution. Some merges include unrelated edits (“evil merges”), and some resolved a conflict in a way that was later reverted. Training learns whatever the tree contains. Scope the range to merges you trust.

# Learn only from merges into main by your integration process, not ad hoc local merges
git rerere-train --first-parent --merges --author='integration-bot' main
# Exclude a known-bad period
git rerere-train main ^v2.3.0 --since=2026-04-01

If training learned something wrong, remove that entry with git rerere forget <path> during the next conflict on that file, as described in forgetting a bad rerere resolution.

Step 5 — Use the trained cache on the next re-merge Jump to heading

With the cache populated, rebase or re-merge as usual. Resolved hunks come back already resolved; git rerere status and git rerere diff show what was reused.

git rebase main feature/long-lived
git rerere status          # files where a recorded resolution was applied
git rerere diff            # what the reused resolution changed
git diff                   # review everything before staging
A re-merge with an empty cache and a trained oneWith an empty cache, every recurring conflict must be resolved again by hand, and resolutions may drift from the original. With a trained cache, recurring conflicts are resolved exactly as before, and only new ones need attention.Empty cacheTrained cacherecurring conflictsresolved by hand againresolved automaticallyconsistencymay differ from last timeidentical to historynew conflictsby handby handtraining never resolves a conflict history did not already contain

Step 6 — Re-train after a large history import Jump to heading

When history arrives from elsewhere — a repository migration, a merge of two repositories, or a long-lived fork being brought back — it brings merge commits your cache has never seen. Training on just the imported range is quick and gives the next integration a head start.

# After importing another repository's history under a new ref
git rerere-train refs/imported/legacy/main ^main

Treat imported merges with the same scepticism as your own: if the other team’s history contains evil merges or reverted resolutions, limit the range accordingly. A merge you have not reviewed is a resolution you are choosing to trust.

Validation checklist Jump to heading

Frequently Asked Questions Jump to heading

How long does training take? Jump to heading

It re-performs each merge, so time scales with the number of merges and the size of the trees. A few hundred merges in a medium repository typically take minutes. Limiting the range keeps it quick.

Will training change any branch? Jump to heading

No. It works on a detached HEAD and resets after each merge. Running it in a separate worktree also keeps your working directory untouched.

Do trained resolutions expire? Jump to heading

Yes, like any rerere entry: unused resolved entries are pruned after sixty days and unresolved ones after fifteen by default. Adjust gc.rerereResolved and gc.rerereUnresolved if you train for a merge that is months away.