How to: Create a git Merge Conflict

Creating a git merge conflict is easier than you think. It usually naturally occurs when git doesn't know which change to accept into a branch, while merging. Typically you want to avoid them, but for educational purposes or just to get a better understanding of them, let's create a git merge conflict.

Merge conflicts in git happen, when two branches were changed on the same line or in the same content of a file before a merge. If you just extend a file or append something, git usually just figures it out by itself.

This tutorial will make use of the command line, but you can do the same with various git GUI clients. When git doesn't know which version of a file to keep, it will insert some lines into the respective source code file and it will end up looking somewhat like this:

# How to create a merge conflict

<<<<<<< HEAD
First you add a file, but create a conflicting change

on another branch.
=======
First you add a file.

Then you add something on another branch and commit it.
>>>>>>> new_branch

The arrows indicate which branch you're currently on, HEAD and from which branch the conflicting change occurs in the merge, new_branch in this case.

If you want to reproduce a merge conflict by yourself, you can run the following script:

#!/bin/bash
mkdir git-repo
cd git-repo
git init
touch my_code.sh
git add my_code.sh
echo "echo Hello" > my_code.sh
git commit -am 'initial'
git checkout -b new_branch
echo "echo \"Hello World\"" > my_code.sh
git commit -am 'first commit on new_branch'
git checkout master
echo "echo \"Hello World!\"" > my_code.sh
git commit -am 'second commit on master'
git merge new_branch

If you want to improve the script, feel free to send me a pull request to the create-conflic.sh gist. To run it, save it as create-conflict.sh, make it executable and run it in a directory, where it will create the git-repo directory.

It produces the following output:

git-merge-conflict $ ./create-conflict.sh
Initialized empty Git repository in /home/geronimo/projects/git-merge-conflict/git-repo/.git/
[master (root-commit) 2054cdd] initial
 1 file changed, 1 insertion(+)
 create mode 100644 my_code.sh
Switched to a new branch 'new_branch'
[new_branch ce5fc6d] first commit on new_branch
 1 file changed, 1 insertion(+), 1 deletion(-)
Switched to branch 'master'
[master 5642b8a] second commit on master
 1 file changed, 1 insertion(+), 1 deletion(-)
Auto-merging my_code.sh
CONFLICT (content): Merge conflict in my_code.sh
Automatic merge failed; fix conflicts and then commit the result.

After this the contents of the my_code.sh file are the following:

<<<<<<< HEAD
echo "Hello World!"
=======
echo "Hello World"
>>>>>>> new_branch

This is because the same line was changed on master and new_branch and git doesn't know which one we would like to keep, so it kindly asks us, by putting lots of <, = and > in our file. If this is kind, is another dispute.

Putting the Merge in Merge Conflict

When we run the git merge we will be notified that something went wrong and we'll get the chance to fix this. We can now manually delete all the kind reminder lines and alter the file so it fits what we want, either the version with or without the ! after Hello World.

We can also make use of a graphical tool to merge, which in many ways can be more visual and desireable, so we can run the command git mergetool and if for example meld is installed, you can use it to merge manually.

git-repo (master)$ git merge new_branch
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
git-repo (master)$ git mergetool

This message is displayed because 'merge.tool' is not configured.
See 'git mergetool --tool-help' or 'git help config' for more details.
'git mergetool' will now attempt to use one of the following tools:
meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare emerge vimdiff
Merging:
README.md

Normal merge conflict for 'README.md':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (meld):

The log from above shows that git will ask you which tool to use when resolving a merge conflict. I'd suggest trying out a few and seeing what your're most comfortable with. Personally I use meld, as seen on the screenshot.

During the merge, multiple files will be created, for the purpose of merging and displaying the different versions. This way the process is easy to understand for other software that you might want to integrate into your workflow.

In this example the files are be:

  • my_code.sh (original file)
  • my_code.sh.BACKUP.9326.sh
  • my_code.sh.BASE.9326.sh
  • my_code.sh.LOCAL.9326.sh
  • my_code.sh.REMOTE.9326.sh

After we quit meld, we will be asked if we accomplished what we wanted to, if we didn't change the file.

README.md seems unchanged.
Was the merge successful? [y/n] n
merge of README.md failed

If you interrupt this with CTRL+C, you'll keep the created files, if you hit n, they will be removed.

Summary

Now we have successfully created a merge conflict in git and hopefully gained a better understanding what makes merge conflicts happen in the first place. If you have any additions, feel free to drop a comment or talk to me on the social media channels listed ;)

Update: This github repository has some more merge conflicts for you to play with (via reddit)

Tagged with: #git #meld #merge conflict

Thank you for reading! If you have any comments, additions or questions, please tweet or toot them at me!