- Kickstart tutorial
- Must-read tutorial: the concepts of branching and merging note the collaborating link at the bottom
- A branching top-down view
- How to resolve merge conflicts in Git? - Stack Overflow Very good hints below the solution.
- Github's help for merging from commandline
Skip to the relevant sections if needed.
- Concepts for resolving
Git conflicts
- Setting up different editors / tool for using
git mergetool
mergetool
simple code example forvimdiff
- Other great references and tutorials
For using mergetool
in git
, we need to understand the following terminology to understand what is being merged:
LOCAL
- thehead
for the file(s) from the current branch on the machine that you are using.REMOTE
- thehead
for files(s) from a remote location that you are trying to merge into yourLOCAL
branch.BASE
- the common ancestor(s) ofLOCAL
andBASE
.MERGED
- the tag /HEAD
object after the merge - this is saved as a new commit.
Common mergetool
from editors will display both LOCAL
and REMOTE
so you can decide which changes to keep.
Please read this tutorial explaining the HEAD objects if you do not know what it is. It will help your understanding of Git tremendously.
We have to change the git config
to set a default mergetool. In this example, we will use vimdiff
:
$ git config merge.tool vimdiff
We can also set the editor to display the common ancestor BASE
while we examine what changes are in LOCAL
and REMOTE
with the following setting:
$ git config merge.conflictstyle diff3
Vim
based diff tool: vimdiff
Or consult the community of your favorite editor to see how to do the equivalent operations for your editor.
Do not prompt before launching the merge resolution tool
$ git config mergetool.prompt false
We can bring up the mergetool
:
$ git mergetool
Then it will bring up the different versions of the file in different Vim splits
panels.
+--------------------------------+
| LOCAL | BASE | REMOTE |
+--------------------------------+
| MERGED |
+--------------------------------+
The top left split panel is the LOCAL
, top middle split is BASE
and top right split is REMOTE
.
The bottom split refers to the MERGED
version.
You can find this info in the bottom bar of each split (I have put 3 yellow rectangles to highlight that info).
As you can see form the below image, my Vim
has highlighted the differences in red for me.
Now if your terminal has any GUI capability and you have compiled Vim
correctly with GUI support, you can use your mouse to click on the bottom split to edit it.
Or if you are a Vim
ninja, you can use the keyboard shortcut to move to different splits.
Ctrl w + h # move to the split on the left
Ctrl w + j # move to the split below
Ctrl w + k # move to the split on top
Ctrl w + l # move to the split on the right
Alternatively you can use the arrow keys.
You can either incorporate the changes by manually editing the MERGED
split,
or use Vim
shortcuts pull from one of the LOCAL
, BASE
ad REMOTE
versions.
:diffg RE # get from REMOTE
:diffg BA # get from BASE
:diffg LO # get from LOCAL
save the changes then quit with :wqa
to close all the splits.
Remember to commit the merge.
$ git commit -am 'merged from several branches'
In the middle file (future merged file), you can navigate between conflicts with ]c
and [c
.
Choose which version you want to keep with :diffget //2
or :diffget //3
(the //2
and //3
are unique identifiers for the target/master copy and the merge/branch copy file names).
:diffupdate (to remove leftover spacing issues)
:only (once you’re done reviewing all conflicts, this shows only the middle/merged file)
:wq (save and quit)
git add .
git commit -m “Merge resolved”
Some examples:
Ref1 for the example
Ref2
If you were trying to do a git pull
when you ran into merge
conflicts,
follow all steps in the previous section for using the mergetool
, then do:
$ git rebase –continue
This command will
Forward-port local commits to the updated upstream HEAD.
according to the documentation, meaning your local commits will be pushed to the upstream remote branch
as a new forward commit that doesn't interfere with previous commits.
Hooray now you can claim that you can collaborate with others with Git without messing up with your collaborators' commits.
]c - Jump to the next change.
[c - Jump to the previous change.
do - diff obtain
dp - diff put
zo - open folded text
zc - close folded text
:diffupdate - re-scan the files for differences