Got merge conflict? Here is how to resolve it.

All you wanted was to merge two branches. Instead you got this:

Auto-merging my_func.py
CONFLICT (content): Merge conflict in my_func.py
Automatic merge failed; fix conflicts and then commit the result.

A merge conflict! 😱

It sounds more serious than it actually is. Follow along to learn how to resolve any merge conflict.

Step 1: DON’T PANIC!

Merge conflicts happen when Git is unsure how to merge two snippets of code and wants your input to make sure it doesn’t do anything dumb.

A merge conflict state is a transitory state. You are in the middle of the merge. So at any time during this process, if you feel unsure and want to go back to the state before merge, just abort the process with git merge --abort and no one will get harmed.

Armed with that security, let’s go ahead and resolve some conflicts.

Step 2: Get a view of what has happened.

Let’s say you created a branch called featureX and started making changes to a file called my_func.py. When you were done, you decided to merge from master to update your branch with the latest that has happened on master. That resulted in a merge conflict. To proceed you need to first get a view of the situation. You do that by checking the status of the repo:

$ git status
On branch featureX
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)

        both modified:   my_func.py

no changes added to commit (use "git add" and/or "git commit -a")

The status message above says that the file my_func.py was modified both on master and on your branch. Maybe someone else was also working with that file and it just happens that they have changed the same lines as you and managed to commit to master before you.

Step 3: Resolve some conflicts.

Time to see what this has done to the file. Open that file in your favorite text editor. Now if you have a modern text editor, like Visual Studio Code, you get a view like this:

my_func.py in conflicted state in VSCode

Or you might see something less fancy like this:

<<<<<<< HEAD
def my_func(arg1, arg2):
    return arg1 + arg2
=======
def my_func(a, b):
    c = a + b
    return c
>>>>>>> master

No matter how you see it, here is what that means:

  • Everything between <<<<<<< HEAD and ======= are changes in your branch (where HEAD is.).
  • Everything between ======= and >>>>>>> master are changes on master.

All you have to do is to remove lines that you don’t want and then save the file. Maybe you think your changes are better than what is on master. In that case, delete the lines coming from master and the indicator lines <<<<<<< HEAD, =======, and >>>>>>> master. (Visual Studio Code does all of this for you if you click on Accept Current Change.) At the end, the file should look like this:

def my_func(arg1, arg2):
    return arg1 + arg2

Do this for all the files that are in “both modified” (i.e. conflicting) state.

Step 4: Continue with the merge.

Make sure you add all the files you have fixed:

$ git add my_func.py

Now if you look at the status, you will see that the conflicts are resolved but you are still in the process of merging:

$ git status
On branch featureX
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Basically Git needs your permission to continue. You allow it to continue by making a commit:

$ git commit

You can either accept the default Git commit message or provide your own.

Now if you look at the log, you will see that master has been merged to your branch:

$ git lol
*   85d57d1 (HEAD -> featureX) Merge branch 'master' into featureX
|\  
| * c47eef2 (master) refactor my_func again
| * 4685dca Refactor my_func.
* | 1efdaf1 Change argument names in my_func
|/  
* ac36ba7 Add info to file.
* d3a02a4 First commit

git lol is an alias I made for myself to make git log output more visual. Read about it here.

Done!

Now go out in the world and resolve some conflicts! 💪