Git Course 0%

Rebase conflicts

Intermediate Git CLI ≈ 9 min

What you will learn

  • Why a rebase pauses per commit rather than once
  • Which side is which during a rebase, and why it is reversed
  • continue, skip and abort, and when each is right

After this lesson you can

  • I can resolve a rebase conflict without losing track of where I am

Why this matters

A rebase conflict works the same way as a merge conflict, with two differences that catch people out: it can happen several times in one rebase, and the words "ours" and "theirs" mean the opposite of what you expect. Both follow from what rebase does.

Why it pauses per commit

Rebase replays your commits one at a time onto the new base (lesson 6.7). Each replay is its own small merge, so each can conflict independently. A branch with five commits can stop five times, and the fifth pause may be about a line you already fixed in the second — because you fixed it in that commit, and this is a different one.

Terminal
$ git rebase main
Auto-merging docs/faq.md
CONFLICT (content): Merge conflict in docs/faq.md
error: could not apply e755292... docs: reword licence answer (#42)
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply e755292... docs: reword licence answer (#42)

The hints name all three exits. could not apply <hash>… <message> tells you which of your commits is being replayed, which is the piece of information you need to resolve sensibly.

Where you are

Terminal
$ git status
interactive rebase in progress; onto ba333eb
Last command done (1 command done):
   pick e755292 # docs: reword licence answer (#42)
No commands remaining.
You are currently rebasing branch 'docs/42-faq-wording' on 'ba333eb'.
  (fix conflicts and then run "git rebase --continue")
  (use "git rebase --skip" to skip this patch)
  (use "git rebase --abort" to check out the original branch)

Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)
	both modified:   docs/faq.md

Read the progress line: "Last command done (1 command done)" and "No commands remaining" together say you are on the last of one commit, so finishing this resolution ends the rebase. With five commits it would say how many remain.

Ours and theirs are swapped

During a merge, "ours" is the branch you are on and "theirs" is the one arriving. During a rebase, Git checks out the new base and replays your commits onto it, so from Git's point of view:

--ours / "Current" --theirs / "Incoming"
Merge your branch the branch being merged in
Rebase the base you are rebasing onto (main) your own commit being replayed

This trips up everyone once. The reliable habit: ignore the words and read the text. With merge.conflictstyle zdiff3 (lesson 11.2) you can see the ancestor as well, and it is usually obvious which side is your sentence.

The three exits

Command Use when
git rebase --continue You resolved the conflict; carry on with the next commit
git rebase --skip This commit's change is no longer needed at all: drop it
git rebase --abort Put everything back exactly as it was before the rebase

The full cycle for one conflicted commit:

Terminal
$ # edit the file, delete the markers
$ git add docs/faq.md
$ git rebase --continue
[detached HEAD 79898a6] docs: reword licence answer (#42)
 1 file changed, 1 insertion(+), 1 deletion(-)
Successfully rebased and updated refs/heads/docs/42-faq-wording.

git rebase --continue opens an editor with the original commit message so you can adjust it; save and close, or use GIT_EDITOR=true git rebase --continue to accept it unchanged. The detached HEAD in the output is normal during a rebase and resolves itself at the end, which is what "Successfully rebased and updated refs/heads/…" reports.

Terminal
$ git log --oneline --graph -3
* 79898a6 docs: reword licence answer (#42)
* ba333eb docs: punctuation in licence answer
*   628abe1 Merge branch 'main' of https://gitlab.com/northwind-trails/trailguide

A straight line: your commit now sits on top of the newer main.

When to give up and merge

A rebase that conflicts on commit after commit is telling you the branch has drifted too far. Two better options:

  • git rebase --abort, then git merge main instead: one resolution rather than five (lesson 6.4).
  • Enable git config --global rerere.enabled true beforehand. "Reuse recorded resolution" remembers how you resolved a conflict and replays that answer when the same conflict appears again, which is exactly the repeated-conflict case.

Neither is a failure. Rebase is a convenience, and a merge is always correct.

Common mistakes

  • Taking "ours" as your work. Reversed during a rebase; read the text.
  • git rebase --skip to make a conflict go away. It deletes the commit. Abort instead if you are unsure.
  • Forgetting the rebase is unfinished. git status says "rebase in progress"; commands like git switch refuse until you continue or abort.
  • git commit instead of git rebase --continue. It creates a stray commit inside the rebase. If you did, git rebase --abort and start again.
  • Forgetting the force push afterwards. The branch was rewritten, so a plain push is rejected (lesson 6.7).

Try it yourself

Goal: hit a rebase conflict, resolve it, and try the abort as well.

  1. From main, create docs/rebase-conflict, change one FAQ line, commit.
  2. Switch to main, change the same line differently, commit.
  3. Switch back to the branch and run git rebase main.
  4. Read the conflict message and git status; note which of your commits is being applied.
  5. Abort with git rebase --abort and confirm with git log --oneline -2 that your commit is unchanged.
  6. Rebase again, this time resolving: edit, git add, GIT_EDITOR=true git rebase --continue.
  7. git log --oneline --graph -3.

Expected result: step 5 restores the branch exactly; step 6 ends with "Successfully rebased and updated"; step 7 shows a straight line with your commit on top of main's.

Show solution

Aborting first is worth doing deliberately once, so that the escape hatch feels available under pressure. Note in step 6 that the commit keeps its message but gets a new hash, which is the rewriting that makes the force push necessary afterwards.

Check yourself

1. During a rebase, --ours refers to…
2. git rebase --skip does what?
3. Your rebase conflicts on three of five commits. What is a reasonable response?

Key terms

Rebase Merge conflict Commit Rewriting history