rerere for long-lived topic branches Jump to heading

A topic branch that lives for months — a major upgrade, a large refactor, a feature behind a long approval process — drifts from main every day. The usual advice is to integrate often so conflicts stay small. But each integration costs something: merging main in clutters the branch’s history, and rebasing makes you resolve the same conflicts again every time. rerere changes the economics. You can do throwaway test merges against main as often as you like, resolve each conflict once, discard the merge, and keep the branch’s history clean. When the real merge or rebase finally happens, every conflict you already saw resolves itself. This page describes that routine, within rerere conflict automation.

When to use this approach Jump to heading

  • A topic branch will live for weeks or months while main keeps moving.
  • You want to know about conflicts early without merging main into the branch every time.
  • You prefer to rebase the branch before merging and want to avoid resolving the same conflicts on each rebase.
  • You maintain a long-lived branch in the sense of keeping a long-lived branch in sync with main, and want less pain doing it.

Step 1 — Enable rerere for the repository Jump to heading

git config rerere.enabled true
git config merge.conflictStyle zdiff3
# keep resolutions longer than the defaults, to cover the branch's lifetime
git config gc.rerereResolved 180
git config gc.rerereUnresolved 30

The default expiry for resolved entries is sixty days. A branch that lives longer than that would lose its earliest resolutions just before the final merge, so extend it.

Step 2 — Do a throwaway test merge regularly Jump to heading

Merge main into a temporary branch, not into the topic branch. Resolve whatever conflicts appear, commit to record the resolutions, then delete the temporary branch. The topic branch is untouched; rerere has learned.

git switch -c test-merge/$(date +%F) feature/upgrade
git merge origin/main
# resolve conflicts, then:
git add -A && git commit --no-edit
# optionally run the tests to see whether the combination works
make test || echo "integration issues to fix on the branch"
git switch feature/upgrade && git branch -D test-merge/$(date +%F)
A long-lived branch with weekly test mergesEach week a throwaway merge of main into a temporary branch surfaces new conflicts, which are resolved once and recorded by rerere. The topic branch's history stays clean. At the final rebase, every previously seen conflict resolves automatically.Test merge3 conflicts, recordedweek 1Test merge1 new conflictweek 2Test merge0 newweek 3Test merge2 new conflictsweek 6Final rebaseall known, autoweek 8each conflict costs you once, however many times the branch is rebased A long-lived branch with weekly test mergesEach week a throwaway merge of main into a temporary branch surfaces new conflicts, which are resolved once and recorded by rerere. The topic branch's history stays clean. At the final rebase, every previously seen conflict resolves automatically.Test merge3 conflicts, recordedweek 1Test merge1 new conflictweek 2Test merge0 newweek 3Test merge2 new conflictsweek 6Final rebaseall known, autoweek 8each conflict costs you once, however many times the branch is rebased
# Verification: rerere has entries from the test merge
ls "$(git rev-parse --git-common-dir)/rr-cache" | wc -l
Test merges leave the topic branch untouchedEach week a temporary branch is created from the topic tip and main is merged into it. The conflicts are resolved and recorded by rerere, the temporary branch is deleted, and the topic branch continues with only its own commits.the merge happens on a throwaway branchmainM1M2M3M4topicT1T2T3T4test-merge wk1T2 + M2test-merge wk2T4 + M4rerere keeps the resolutions; the merge commits themselves are thrown away Test merges leave the topic branch untouchedEach week a temporary branch is created from the topic tip and main is merged into it. The conflicts are resolved and recorded by rerere, the temporary branch is deleted, and the topic branch continues with only its own commits.the merge happens on a throwaway branchmainM1M2M3M4topicT1T2T3T4test-merge wk1T2 + M2test-merge wk2T4 + M4rerere keeps the resolutions; the merge commits themselves are thrown away

Step 3 — Fix integration problems on the branch itself Jump to heading

A test merge may reveal more than textual conflicts: code that merges cleanly but fails to build or pass tests together. Fix those on the topic branch as ordinary commits, so the fix travels with the branch rather than living only in a throwaway merge.

git switch feature/upgrade
# e.g. main renamed a function the branch calls
git grep -n 'old_function_name' -- src/
sed -i 's/old_function_name/new_function_name/g' src/upgrade/*.py
git commit -am "Follow main's rename of old_function_name"

The class of problem — changes that merge cleanly but conflict in meaning — is covered in catching semantic conflicts in CI.

Step 4 — Rebase or merge for real, and let rerere work Jump to heading

When the branch is ready, rebase it onto main (or merge it). Recorded resolutions apply automatically; review them before continuing.

git switch feature/upgrade
git rebase origin/main
# for each stop:
git rerere diff         # resolutions rerere applied
git diff                # anything still conflicted
git add -A && git rebase --continue
Three ways to keep a long branch currentMerging main into the branch regularly records every integration in the branch's history. Rebasing regularly keeps history linear but repeats conflict resolution each time. Throwaway test merges with rerere surface conflicts early, keep history clean, and make the final rebase mostly automatic.Branch historyRepeated conflict workmerge main in weeklymany merge commitsnonerebase weeklylinearevery rebasetest merge + rererelinearonce per conflictthe third option needs rerere — without it, test merges are wasted effort Three ways to keep a long branch currentMerging main into the branch regularly records every integration in the branch's history. Rebasing regularly keeps history linear but repeats conflict resolution each time. Throwaway test merges with rerere surface conflicts early, keep history clean, and make the final rebase mostly automatic.Branch historyRepeated conflict workmerge main in weeklymany merge commitsnonerebase weeklylinearevery rebasetest merge + rererelinearonce per conflictthe third option needs rerere — without it, test merges are wasted effort

A rebase replays each topic commit separately, so a conflict that appeared once in a test merge may appear in pieces across several commits during a rebase. rerere matches hunks, so the pieces often still resolve, but expect a few to need attention.

Step 5 — Share the resolutions if others work on the branch Jump to heading

If several people work on the long-lived branch, each person’s rerere cache knows only the conflicts they resolved. Share them, or have one person own integration.

# Simplest sharing: train from the test-merge commits before deleting them
git rerere-train test-merge/2026-10-02

Or push test-merge branches under a namespace others can train from; the techniques are in sharing rerere resolutions across a team.

Validation checklist Jump to heading

Frequently Asked Questions Jump to heading

Why not just merge main into the branch regularly? Jump to heading

That is a perfectly valid approach and needs no rerere. The test-merge approach suits teams that want the final history to show the branch as a clean series of commits on top of main.

Do I need to run tests on each test merge? Jump to heading

It is the most valuable part. Textual conflicts are the easy problem; a test run on the merged state reveals the behavioural conflicts that would otherwise appear only after the real merge.

What if a conflict changes between test merges? Jump to heading

If main changes the conflicting lines again, the conflict’s content changes and rerere sees it as a new conflict. You resolve it once more, and the new resolution is recorded alongside the old.