Repeated conflicts when rebasing vs merging Jump to heading

Rebasing a branch with eight commits onto a main that changed the same function as your first commit produces a conflict. You resolve it. The second commit touches the same function again and conflicts again, against your own resolution. By the fifth commit you are resolving the same region for the fifth time. Next week, after another rebase, you do it all again. Merging main into the branch would have asked once. This is not a flaw in Git but a direct consequence of how each operation works: a rebase replays commits one at a time, a merge combines end states once. Knowing why the repetition happens tells you how to avoid it — by squashing, by remembering resolutions, or by merging instead. This page explains the mechanics and the fixes, within merge vs rebase decision matrix.

When to use this approach Jump to heading

  • A rebase stops on conflict after conflict in the same file.
  • You resolve the same conflicts every time you rebase a long-lived branch.
  • You are choosing between rebasing and merging for a branch with many commits touching contested code.
  • Conflicts during rebase feel harder to understand than during a merge.

Step 1 — See why a rebase asks per commit Jump to heading

A merge compares the branch tip with main’s tip, against their common base: one three-way merge, so each conflicting region is resolved once. A rebase applies each commit in turn on top of main, so a region that several commits touch conflicts in each of them, each time against the result of the previous resolution.

One merge against a sequence of replaysA merge combines the branch's final state with main's final state once, so a contested region conflicts once. A rebase replays each commit separately; if five commits touch the contested region, the region can conflict five times, each against the previous resolution.merge mainrebase onto mainoperationsone three-way mergeone per commitregion touched by 5 commits1 conflictup to 5 conflictseach resolution againstboth final statesthe previous replayhistorymerge commit addedlinearthe rebase is not wrong — it is answering a more detailed question
# How many of the branch's commits touch the contested file?
git log --oneline origin/main..HEAD -- src/billing/totals.py | wc -l

If that number is high and main also changed the file, expect a conflict per commit.

Step 2 — Squash the contested commits before rebasing Jump to heading

If the intermediate commits are not valuable on their own — “wip”, “fix test”, “address review” — squash them first. One commit touching the region means one conflict.

# Squash the branch into one commit on its existing base, then rebase once
base=$(git merge-base origin/main HEAD)
git reset --soft "$base" && git commit -m "feat(billing): credit note totals rework"
git rebase origin/main          # one replay, at most one conflict per region

When the commits are worth keeping separately, squash only the ones touching the contested area with an interactive rebase on the existing base before rebasing onto main. The techniques are in squashing without interactive rebase.

Step 3 — Let rerere remember resolutions across rebases Jump to heading

When the same branch is rebased repeatedly, each rebase meets the same conflicts. rerere records each resolution and reapplies it automatically the next time it sees the same conflict.

git config --global rerere.enabled true
git rebase origin/main
# "Resolved 'src/billing/totals.py' using previous resolution."
git rerere diff          # review what was reused
git add -A && git rebase --continue
Conflicts resolved by hand across repeated rebasesAn illustrative branch rebased weekly for a month. Without rerere, the same five conflicts must be resolved by hand every week. With rerere, the first rebase records them and later rebases only need hand resolution for genuinely new conflicts.conflicts resolved by hand per rebase (illustrative)week 1, no rerere5week 2, no rerere5week 1, rerere5week 2, rerere1week 3, rerere0rerere turns repeated conflicts into a one-time cost

The details are in automating repeated conflict resolution with rerere, and for long branches in rerere for long-lived topic branches.

Step 4 — Merge main in when replay adds nothing Jump to heading

If the branch’s commit history matters less than avoiding repeated work, merge main into the branch instead. Each region conflicts once, the resolution is recorded in the merge commit, and future merges build on it rather than repeating it.

git merge origin/main             # one combined resolution
git push                          # no force needed

If the team requires linear history on main, the branch can still be squash-merged at the end; the intermediate merges of main disappear in the squash.

Step 5 — Resolve each replayed conflict by the commit’s intent Jump to heading

When you do rebase through several conflicts, the key is to resolve each one as “what did this commit change, applied to the current code” — not “make the file look like my branch’s final version”. Jumping straight to the final version makes later commits empty or wrong.

# At each stop: what is this commit trying to do?
cat .git/rebase-merge/message             # the commit being replayed
git show "$(cat .git/rebase-merge/stopped-sha)" -- src/billing/totals.py
Facing a run of rebase conflictsIf the branch's commits are not individually valuable, abort and squash first, then rebase once. If they are valuable and the branch will be rebased again, enable rerere and resolve each by the commit's intent. If neither history nor linearity matters, abort and merge main in.Do the branch's individual commits matter?noSquash, then rebaseone conflictyes, rebased oftenrerere + intentresolve once eachlinearity doesn't matterMerge main inone resolutiongit rebase --abort is always available if the run is longer than expected

Step 6 — Abort early when the run is long Jump to heading

If the first conflicts show the rebase will be a long series, abort and choose a better approach rather than grinding through.

git rebase --abort                 # back to exactly where you started

Validation checklist Jump to heading

Frequently Asked Questions Jump to heading

Is the final result different between merging and rebasing? Jump to heading

The final tree should be the same if conflicts are resolved consistently. What differs is history: a merge records one resolution in a merge commit; a rebase spreads resolutions across rewritten commits.

Why are rebase conflicts harder to understand? Jump to heading

Each conflict compares main with one intermediate commit rather than with your final code, and “ours” and “theirs” are reversed. Enabling zdiff3 and reading the commit being replayed make them much clearer.

Can git rebase --rebase-merges help? Jump to heading

Not with repetition; it preserves merge commits within the branch. Repetition comes from replaying several commits that touch the same lines, which happens either way.