Git is very good at merging code. Merges are local, fast, and flexible. Naturally every time one merges content from different branches conflicts can and will happen. Often solving a conflict is as simple as knowing and choosing the leading change. Sometimes resolving a conflict requires more work.
Every developer has a different preference in how they solve conflicts. So a while ago fellow writer Dan Stevens used Questions for Confluence internally to ask how people did it.
The answers and insight collected have much broader appeal than the walls of Atlassian and so below is an expanded and annotated collection of the many ways we solve Git conflicts. Hopefully it will provide ideas and things to try and incorporate in your daily coding practice.
General setup tips
Let's start with a simple set of basic configuration toggles to setup Git properly for merges.
1. Setup tips
When you have a conflict, you can initiate your merge sessions from the command line typing "
git mergetool" or from a visual tool.
To setup Git with your favorite conflict resolution software use the "
merge.tool" variable in "
For example someone using KDiff3 might fill the "
.gitconfig" merge section like:
The above is equivalent to typing from the command line:
git config --global merge.tool kdiff3
2. Show common ancestor in conflict markers
Use the following setting to improve the conflict markers to show also the common ancestor (Thanks Robin Stocker and Hugh Giddens):
git config --global merge.conflictstyle diff3
The setting annotates the conflict by adding a new section with marker
||||||| to show how the conflicting lines looked at the commit which is the
common ancestor of the two branches in question.
3. Use the "patience" algorithm in merges
If you have lots of conflicts in a long piece of content like an
XML file or when two versions have diverged a lot, try merging again using:
git merge --strategy-option=patience
The result of the
patience algorithm should help reconcile better the misaligned brackets in functions and tags. Some details on the algorithm can be found on this Stack Overflow answer.
4. When you need information on the history of a single file
Barring using a visual tool like SourceTree to find out what happened to a file you can use:
git log --merge --decorate --source -p path/to/file/you/care/about
Solving conflicts manually
There are two broad schools of thought in working through merges: some developers like to use a low-level process and manipulate conflict markers by hand and some prefer to be aided by a visual tool. Both can be extremely effective.
5. Sample process
Several colleagues shared their manual process, for example Jason Hinch reported his flow:
Start with the merge at hand:
git merge the/other/branch git status
Have a look at how many/which files conflicted.
For each conflicting file:
- Open the file in editor of choice (i.e. IntelliJ or vim)
- Look at each block wrapped in conflict markers ("
>>>>" and "
- See if it makes sense, what was the intention of each author, resolve it if you can figure it out.
If the conflict markers don't make sense - often when files have changed significantly - run:
git diff HEAD...the/other/branch -- path/to/conflicting/file git diff the/other/branch...HEAD -- path/to/conflicting/file
You do this to see which side is the smaller change.
Often the commands:
git log -p HEAD..the/other/branch -- path/to/conflicting/file git log -p the/other/branch..HEAD -- path/to/conflicting/file
can shed further light on what changed on either side.
Revert the file to the side which has the most changes:
git checkout the/other/branch -- path/to/conflicting/file
(Alternatively you could also use
git checkout --theirsor
Manually go though and reapply the changes performed on the other side to the file:
git add path/to/conflicting/file
When all the changes have been fixed build the project, ensuring that it at least compiles - if the tests are quick to run, run them as well:
This may seem a little manual, but Jason found it results in fewer bad merges for his workflow.
For a hands on step by step basic video on how to solve conflicts manually checkout our recent Git Power Routines course.
Parade of merge tools
There are many different visual tools to perform complex merge and conflict resolutions. My colleagues have mentioned a wide - non exhaustive - range.
6. IntelliJ IDEA conflict resolution tool
IntelliJ IDEA is the IDE of choice of many Atlassians. Many use the built-in IntelliJ IDEA conflict resolution tool to deal with conflicts. It provides three panes for analysis: local, remote and merge result.
KDiff3 is part of the KDE product suite and was mentioned a few times in our internal survery.
Steve Streeting - original author of SourceTree - and several other colleagues uses P4Merge for merges.
P4Merge is a free visual tool and has four panes instead of the three other tools provide.
The panes show the "
remote" and "
Developed using GTK+ and Python, meld has been around for a long time as well and was mentioned by a few.
10. tig for status + diff
11. OS X FileMerge aka opendiff
In the long list of suggestions a couple of developers mentioned the native
opendiff" tool from OS X, otherwise named "FileMerge".
I don't know much about diffmerge but it was mentioned too in the list.
13. Araxis Merge (commercial)
This name - Araxis Merge - reminds me of a time long ago when I was working on a locked down Windows machine trying to survive a sea of XML files madness and the tool proved to be up to the challenge. It's a commercial tool.
Several colleagues use vimdiff to solve conflicts. That is vim's own merge/diff tool. You can set it up by typing:
git config merge.tool vimdiff git config merge.conflictstyle diff3 git config mergetool.prompt false
Or directly modifying the
.gitconfig file as shown above.
You might also enjoy our ebook, "Hello World! A new grad's guide to coding as a team" – a collection of essays designed to help new programmers succeed in a team setting. Grab it for yourself, your team, or the new computer science graduate in your life. Even seasoned coders might learn a thing or two.