How does git rerere work internally, and how do you use it effectively in workflows involving repeated rebases and long-lived branches?
Quick Answer
git rerere (reuse recorded resolution) caches conflict resolutions by hashing the conflict state and storing the resolution diff in .git/rr-cache/. When the same conflict appears again during rebase, merge, or cherry-pick, rerere automatically applies the cached resolution. It is essential for workflows with frequent rebasing onto a changing mainline or maintaining long-lived release branches.
Detailed Answer
Think of rerere like a court's case law system. The first time a specific legal dispute arises, a judge makes a ruling. The ruling is recorded with all relevant context. When an identical dispute comes before the court again, the clerk looks up the precedent and applies the same ruling automatically, without requiring the judge's time. The key is that the dispute must be structurally identical; even a small change in the facts (conflict content) produces a different case number (hash) and requires a new ruling.
Git rerere is enabled with git config rerere.enabled true. When a merge, rebase, or cherry-pick produces conflicts, rerere computes a fingerprint (SHA hash) of each conflicted hunk by normalizing the conflict markers and hashing the content. This fingerprint becomes the directory name under .git/rr-cache/<hash>/. Inside, rerere stores a 'preimage' file (the conflicted state) and, after you resolve the conflict and stage the file, a 'postimage' file (the resolution). The next time Git encounters a conflict with the same fingerprint, rerere automatically applies the stored resolution, staging the file and printing 'Resolved using previous resolution.' You can still review and override the auto-resolution.
Internally, the fingerprint computation strips the branch-name labels from conflict markers (<<<<<<< HEAD becomes generic) and hashes only the conflicting content. This means the same logical conflict produces the same hash regardless of which branch names are involved. The .git/rr-cache/ directory accumulates entries over time; git rerere gc cleans up entries older than the configured expiry (gc.rerereResolved defaults to 60 days for resolved entries, gc.rerereUnresolved to 15 days for unresolved). The git rerere diff command shows the current conflict alongside the recorded resolution, and git rerere forget <path> clears a specific cached resolution if you realize it was wrong. Rerere also works with git rerere remaining to show which conflicts still need manual resolution after auto-resolutions have been applied.
The primary production use case for rerere is repeated rebasing. Consider a feature branch that takes three weeks to develop, with daily rebases onto main to stay current. Without rerere, if a conflict occurs at the same point during each rebase, you resolve it manually every single day. With rerere, you resolve it once, and every subsequent rebase applies the same resolution automatically. This is also invaluable for release branch maintenance: when cherry-picking fixes from main to release/v3.x, the same file might conflict repeatedly due to diverged context. Rerere caches each resolution and applies it silently. Advanced teams share rerere caches across developers using git rerere-train scripts that replay merge history to pre-populate the cache, or by syncing .git/rr-cache/ through a shared network location. Some teams even check rerere cache data into a separate branch for team-wide sharing.
A critical gotcha: rerere applies resolutions silently, which means a wrong resolution gets replayed without warning. If you resolved a conflict incorrectly and rerere cached it, every future occurrence of that conflict will be resolved incorrectly too. Always review auto-resolved files with git diff --staged before committing. Use git rerere forget <path> to clear a bad resolution. Another trap: rerere only caches at the hunk level, not the file level. If a file has two conflicted hunks, rerere might auto-resolve one and leave the other for manual resolution. Also, rerere does not auto-stage files in all Git versions; check your version's behavior and always run git status after a merge/rebase to verify. Finally, rerere data is local and not pushed to remotes, so each developer builds their own cache unless your team implements cache sharing.