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.
# 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 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 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.
Related Jump to heading
- Merge vs Rebase Decision Matrix — the parent topic.
- Rebasing a Feature Branch Before Merge — the rebase workflow this page refines.
- Ours and Theirs During Merge vs Rebase — reading rebase conflict markers.
- Merge vs Rebase for Long-Running Branches — where repetition hurts most.