Rebase Conflicts

Updated

October 30, 2026

Rebase Conflicts: How They Differ from Merge Conflicts

After this page you can finish a conflicted rebase one commit at a time.

One commit at a time

A merge conflict happens once, at the join. A rebase conflict happens each time a copied commit does not apply onto the new parent.

 merge: one fight at M

 A ← B ← C ← M
      ↑      ↑
      D ← E

 rebase: a fight at D', then maybe again at E'

 A ← B ← C ← G ← D'  ←  E'
                 ▲ stop    ▲ stop

Markers look the same (<<<<<<<). git status during a rebase says rebase in progress and names the commit being applied.

git rebase main
# CONFLICT (content): Merge conflict in src/ping.py
git status

The loop

  1. Edit files, remove markers.
  2. git add the resolved paths.
  3. git rebase --continue (not git commit, unless Git asks you to).
  4. Repeat until Git prints Successfully rebased.
nvim src/ping.py
git add src/ping.py
git rebase --continue

If the commit becomes empty (your patch is already in the new base):

git rebase --skip

Give up:

git rebase --abort

Ours / theirs are swapped from merge

During merge, --ours is the branch you had checked out (main). During rebase, you checked out the feature and Git replays onto main: --ours is the upstream (the new base), --theirs is the commit being replayed.

That swap surprises everyone once. Prefer reading the markers over --ours until it is boring.

rerere

With rerere.enabled (chapter 2), Git records the resolution. A later rebase that hits the same hunk applies it again. On a long-lived feature branch that rebases onto main daily, this is the difference between pain and a two-second continue.

After success

git log --oneline --graph --decorate main feat/ping-json

A straight line from main through your copied commits. Then git switch main && git merge --ff-only feat/ping-json.