• Skip to primary navigation
  • Skip to main content
Sal Ferrarello
  • About Sal Ferrarello
  • Speaking
  • Connect
    Twitter GitHub
You are here: Home / Dev Tips / Resolving Git Rebase Merge Conflicts

Resolving Git Rebase Merge Conflicts

Last updated on February 2, 2021 by Sal Ferrarello

When performing a Git rebase, I often find myself in the situation where I have one or more merge conflicts. This is how I resolve these merge conflicts.

Note: When resolving a git rebase merge conflict, Git will open your text editor to modify your commit message. By default, Git uses Vim which is not the most user friendly editor. I suggest you set Git to use your preferred editor (see how to set your Git commit message editor).

What is a Merge Conflict

In Git Rebase with Blocks, we looked at how rebasing:

  • finds the most recent common commit between the two branches
  • temporarily removes any newer commit(s) from our branch
  • updates our branch to match the branch the other branch
  • then re-applies our temporarily removed commit(s)

When we re-apply our temporarily removed commits, they are being re-applied to code that may have changed.

Imagine if the commit being re-applied renamed a function but due to the rebase that function no longer exists. Git can not automatically determine how to apply this commit, so a merge conflict is created.

Example of a Merge Conflict

We create a text file (letters.txt) with letters in alphabetical order. We add the letter “A” in a commit and then we add the letter “B” in another commit.

(main)     
B
A

We decide to create a new branch (called feat/d) in order to introduce our new feature (the letter “D”).

(main)     (feat/d*)
           D
B          B
A          A

Based on this we could do a fast-forward merge of feat/d into main (because main is an ancestor of feat/d).

Unfortunately, someone has already added another commit to main while we were working on our branch.

(main)     (feat/d*)
C          D
B          B
A          A

Rebasing our Feature Branch

Now we can’t do a fast-forward merge (because the latest commit on main, D does not appear in our feat/d branch), so we run git rebase main on our feat/d branch to bring it up to date.

(main)     (feat/d*)
           D

C          C
B          B
A          A

but when we try to re-apply our D commit, Git doesn’t know if the letter “D” goes before or after “C”.

CONFLICT (content): Merge conflict in letters.txt
error: could not apply 163fe29... D
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 163fe29... D

Now if we look inside letters.txt, we’ll see a section that looks like this

<<<<<<< HEAD
C
=======
D
>>>>>>> 163fe29... D

Note: Some browsers (e.g. Visual Studio Code) provide additional UI options to assist with resolving merge conflicts.

VSCode Merge Conflict Ui.

Branches During our Merge Conflict

Our merge conflict occurred at this moment where we’ve added commit C to our feat/d branch but we’ve not yet re-applied our commit D.

(main)     (feat/d*)
           D

C          C
B          B
A          A

Looking again at the merge conflict in our file, we can see our two different versions. In the top half (labeled HEAD) we can see how this code appears in commit the branch thus far (at the moment of commit C).

In the bottom half, we see how the code appears in our temporarily removed commit D (which has a commit hash of 163fe29).

<<<<<<< HEAD
C
=======
D
>>>>>>> 163fe29... D

Fixing Our Code

Using these two different versions of the code, it is our job to modify the code as needed. Sometimes this involves keeping one block and discarding the other block. In our case, we need the information from both blocks put in the correct order (and removing the Git marker lines).

C
D 

Resolving Our Merge Conflict

Stage Our Changes

Once our code is fixed, we add it to our staged changes with

git add letters.txt

Review Our Changes

We can review our changes with

git diff --staged

Remember we are trying to re-apply our commit C but it didn’t apply cleanly (Git couldn’t figure out how to apply it). Now we’ve made changes to D, we are previewing this new version of our commit D.

Note: A single commit can have multiple merge conflicts and they all must be resolved before we move on. Previewing the commit (with git diff --staged) allows us to verify there are no unresolved merge conflicts.

Apply Our Updated Commit

We apply our updated commit with

git rebase --continue

Now our feat/d branch has our updated D' commit, which contains the code after our merge conflict was resolved.

(main)     (feat/D*)
           D'
C          C
B          B
A          A

Multiple Commits with Merge Conflicts

If our branch has multiple commits that need to be temporarily removed and then re-applied during the rebase, we may have to resolve multiple merge conflicts (one each time a commit is re-applied). The secret to rebasing multiple commits is viewing the current commit message during the rebase conflict.

One advantage a merge commit has over performing a rebase is you only have to resolve the merge commit one time (rather than once for each commit).

Update Remote

By default, the git push command only adds new commits to a remote branch (e.g. on GitHub).

Because we have rewritten history, we need to overwrite the remote branch (rather than just add commits). To do this we add --force-with-lease to our git push.

git push --force-with-lease
Sal Ferrarello
Sal Ferrarello (@salcode)
Sal is a PHP developer with a focus on the WordPress platform. He is a conference speaker with a background including Piano Player, Radio DJ, Magician/Juggler, Beach Photographer, and High School Math Teacher. Sal can be found professionally at WebDevStudios, where he works as a senior backend engineer.

Share this post:

Share on TwitterShare on FacebookShare on LinkedInShare on EmailShare on Reddit
Warning! This is a draft, not a finalized post. See full draft disclosure.

Filed Under: Dev Tips, Draft, Solution Tagged With: Git, Merge Conflict, rebase

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Copyright © 2022 · Bootstrap4 Genesis on Genesis Framework · WordPress · Log in