DEV Community

James Joyner
James Joyner

Posted on Originally published at moderngitacademy.com AI-assisted

Git Remembers How You Resolved That Conflict — If You Let It

You rebase a long branch onto main. The first commit conflicts in config.yml; you resolve it. The second commit touches the same lines and conflicts in exactly the same way. So does the third. Each time you re-read both sides, re-make the same decision, and re-type the same lines.

Git can remember the resolution. git rererereuse recorded resolution — is one config setting, and it comes with two rules that matter more than the setting. Everything below was run in a disposable repository on git 2.43.0; the output is real.

Enable it (in one repository, to start)

git config rerere.enabled true
Enter fullscreen mode Exit fullscreen mode

No --global — try it here first. From now on, every conflict Git shows you is recorded as a preimage (both sides, branch labels stripped), and the resolution you commit is recorded as the postimage, under .git/rr-cache/.

The first conflict, resolved by hand

Two branches changed timeout in opposite directions. Merge one into the other:

git merge main
Enter fullscreen mode Exit fullscreen mode
Auto-merging config.yml
CONFLICT (content): Merge conflict in config.yml
Recorded preimage for 'config.yml'
Automatic merge failed; fix conflicts and then commit the result.
Enter fullscreen mode Exit fullscreen mode

The third line is rerere already at work. Resolve — deliberately with a third value, so it is clearly a decision:

printf 'timeout: 5000\nretries: 3\nbackoff: exponential\n' > config.yml
git add config.yml
git commit -m "Merge main into feature: settle on 5000"
Enter fullscreen mode Exit fullscreen mode
Recorded resolution for 'config.yml'.
Enter fullscreen mode Exit fullscreen mode

The same conflict, again

Undo the merge (git reset --hard ORIG_HEAD) and rebase instead — same two sides, same clash:

git rebase main
Enter fullscreen mode Exit fullscreen mode
CONFLICT (content): Merge conflict in config.yml
error: could not apply c1359f5... Fail fast: lower timeout
Resolved 'config.yml' using previous resolution.
Enter fullscreen mode Exit fullscreen mode

Git still stops. But look at the file and the index:

cat config.yml
git status --short
Enter fullscreen mode Exit fullscreen mode
timeout: 5000
retries: 3
UU config.yml
Enter fullscreen mode Exit fullscreen mode

The resolution is in the file; the file is still unmerged. That is the first rule: by default rerere writes the resolution and waits for you to inspect it. Look at the combined diff — the line marked ++ is the resolution, and it is the one line you must judge:

git diff
Enter fullscreen mode Exit fullscreen mode
@@@ -1,2 -1,2 +1,2 @@@
- timeout: 10000
 -timeout: 500
++timeout: 5000
  retries: 3
Enter fullscreen mode Exit fullscreen mode

Still right? Then git add config.yml && git rebase --continue. On a ten-commit branch where three commits hit the same hunk, that is three replays, each a diff and an add instead of a fresh decision.

rerere.autoupdate: skip the add

If you trust your recorded resolutions, git config rerere.autoupdate true stages the replayed file too:

Staged 'config.yml' using previous resolution.
Enter fullscreen mode Exit fullscreen mode

The rebase still stops — rerere never continues an operation on its own — but --continue now proceeds without a manual add. Second rule: a replayed resolution going straight into the index is a trust decision. Leave autoupdate off until you have watched it replay in a repository you know.

When it is wrong

The team decides 5000 was the wrong call. git rerere forget config.yml drops the recorded resolution; then git checkout --conflict=merge config.yml puts the markers back so you resolve afresh:

Recreated 1 merge conflict
<<<<<<< ours
timeout: 10000
=======
timeout: 500
>>>>>>> theirs
Enter fullscreen mode Exit fullscreen mode

And the safety property: change either side of the conflict and nothing is replayed. Add a commit on main that also touches retries, merge again, and you get a plain CONFLICT with a new Recorded preimage — rerere only speaks when the conflict is byte-for-byte the one it saw.

What it cannot know

It matches on the conflicted lines, not on the surrounding file, the tests, or the reason the code exists. The same conflict can deserve a different answer a week later. Read the ++ line every time — and run the marker grep before every --continue:

grep -nE '^(<<<<<<<|=======|>>>>>>>)' config.yml && echo "MARKERS REMAIN" || echo "clean"
Enter fullscreen mode Exit fullscreen mode

The full walkthrough — including the git rerere diff view, gc and expiry, why the cache is per-clone, and the mistakes people make with clear versus forget — is the article this is condensed from, with a fixture script that rebuilds the repository: Git rerere: stop resolving the same merge conflict twice. rerere only pays off once resolving a conflict by hand is routine; that is a 20-minute session with a browser simulator: Resolve and verify a merge conflict.

Top comments (1)

Collapse
 
mridul_it_is profile image
Mridul Tiwari

well this was new, I am still unable to comprehend where to use this but at the same time excited to know that there is such a feature at my hands now