Rebase conflicts
Intermediate Git CLI
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.
$ git rebase mainAuto-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
$ git statusinteractive 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.mdRead 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:
$ # 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.
$ 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/trailguideA 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, thengit merge maininstead: one resolution rather than five (lesson 6.4).- Enable
git config --global rerere.enabled truebeforehand. "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 --skipto make a conflict go away. It deletes the commit. Abort instead if you are unsure.- Forgetting the rebase is unfinished.
git statussays "rebase in progress"; commands likegit switchrefuse until you continue or abort. git commitinstead ofgit rebase --continue. It creates a stray commit inside the rebase. If you did,git rebase --abortand 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.
- From
main, createdocs/rebase-conflict, change one FAQ line, commit. - Switch to
main, change the same line differently, commit. - Switch back to the branch and run
git rebase main. - Read the conflict message and
git status; note which of your commits is being applied. - Abort with
git rebase --abortand confirm withgit log --oneline -2that your commit is unchanged. - Rebase again, this time resolving: edit,
git add,GIT_EDITOR=true git rebase --continue. 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.