If you are already a vim and git master and you are impatient, please jump to theQuick start section at the end of this article.
The vimdiff as a merge tool will display several buffers to show the yours/theirs/original changes.
The key point is to set up the vimdiff so that the buffer number in the vimdiff status line is visible.
First, add following code into your ~/.vimrc
<span style="color:#b9ca4a;">set </span><span style="color:#e7c547;">laststatus</span><span style="color:#c397d8;">=</span>2 <span style="color:#969896;font-style:italic">"show the status line</span> <span style="color:#b9ca4a;">set </span><span style="color:#e7c547;">statusline</span><span style="color:#c397d8;">=</span>%<span style="color:#c397d8;">-</span>10<span style="color:#c397d8;">.</span>3n <span style="color:#969896;font-style:italic">"buffer number</span>
Second, if you know the buffer number, you can use hot key like ",2" (press comma first, then press two as quickly as possible) to pull change from buffer number two.Add below code into your ~/.vimrc to set up hot keys:
map <span style="color:#b9ca4a;"><silent></span> <span style="color:#c397d8;"><</span>leader<span style="color:#c397d8;">></span>1 <span style="color:#b9ca4a;">:diffget </span>1<span style="color:#c397d8;"><</span>CR<span style="color:#c397d8;">></span> <span style="color:#b9ca4a;">:diffupdate<</span>CR<span style="color:#c397d8;">></span> map <span style="color:#b9ca4a;"><silent></span> <span style="color:#c397d8;"><</span>leader<span style="color:#c397d8;">></span>2 <span style="color:#b9ca4a;">:diffget </span>2<span style="color:#c397d8;"><</span>CR<span style="color:#c397d8;">></span> <span style="color:#b9ca4a;">:diffupdate<</span>CR<span style="color:#c397d8;">></span> map <span style="color:#b9ca4a;"><silent></span> <span style="color:#c397d8;"><</span>leader<span style="color:#c397d8;">></span>3 <span style="color:#b9ca4a;">:diffget </span>3<span style="color:#c397d8;"><</span>CR<span style="color:#c397d8;">></span> <span style="color:#b9ca4a;">:diffupdate<</span>CR<span style="color:#c397d8;">></span> map <span style="color:#b9ca4a;"><silent></span> <span style="color:#c397d8;"><</span>leader<span style="color:#c397d8;">></span>4 <span style="color:#b9ca4a;">:diffget </span>4<span style="color:#c397d8;"><</span>CR<span style="color:#c397d8;">></span> <span style="color:#b9ca4a;">:diffupdate<</span>CR<span style="color:#c397d8;">></span>
To use vimdiff as default merge tool:
git config --global merge.tool vimdiff git config --global mergetool.prompt false
I already set up a "hello world" project at https://github.com/redguardtoo/test-git-mergetool for your practice.
It has three branches "master", "bob", and "chen".
git clone git://github.com/redguardtoo/test-git-mergetool.git <span style="color:#c397d8;">cd</span> test-git-mergetool git checkout -b bob origin/bob <span style="color:#969896;font-style:italic"># </span><span style="color:#969896;font-style:italic">create local mirror of bob branch</span> git checkout -b chen origin/chen <span style="color:#969896;font-style:italic"># </span><span style="color:#969896;font-style:italic">create local mirror of chen branch</span>
Bob and Chen has edited same files. So please merge branch "bob" into "master" at first. Then merge from "chen". The merge conflicts will be created.
git branch <span style="color:#969896;font-style:italic"># </span><span style="color:#969896;font-style:italic">double check that we got three local branches: master, bob, chen</span> git checkout master <span style="color:#969896;font-style:italic"># </span><span style="color:#969896;font-style:italic">set master branch as main branch</span> git merge bob <span style="color:#969896;font-style:italic">#</span><span style="color:#969896;font-style:italic">this is ok, because bob is the first one to merge changes</span> git merge chen <span style="color:#969896;font-style:italic"># </span><span style="color:#969896;font-style:italic">now some conflicts created because Bob has already edited and merged same files</span>
Now start merge tool:
git mergtool
Git will invoke vimdiff with the following window layout. There are four buffers in this layout:
Here is the explanation of each buffer:
Buffer | Explanation | Buffer Number |
---|---|---|
THEIRS | contents of the file on the current branch | 2 |
BASE | common base for the merge | 3 |
YOURS | contents of the file to be merged. | 4 |
MERGED | The file containing the conflict markers. You need edit and commit this file. | 1 |
You could use hot key ",2" (comma + two) ",3" (comma+three) ",4" (comma+four) to pick the content you want to use (either THEIRS or BASE or YOURS) to replace the marked conflict in MERGED buffer whose buffer number is one.
Or you can edit the content directly in MERGED buffer. Anyway, git only care about the the file binding to MERGED buffer. Any other buffer will be ignored by git.
You can use hot key "[c" and "]c" to navigate to previous/next conflict (including the conflict resolved by git automatically) in current file which is binding to MERGED buffer.
After finishing editing of the conflicting file in MERGED buffer, you can use hot key ":xa" to exit vimdiff. Git will open next conflicting file with vimdiff automatically.
When you have resolved all the conflicts, follow the hint of git to commit your changes.
You can use command line like "git mergetool -t vimdiff" to start vimdiff from git.
So the minimum set up is adding three lines of code into your ~/.vimrc:
map <span style="color:#b9ca4a;"><silent></span> <span style="color:#c397d8;"><</span>leader<span style="color:#c397d8;">></span>2 <span style="color:#b9ca4a;">:diffget </span>2<span style="color:#c397d8;"><</span>CR<span style="color:#c397d8;">></span> <span style="color:#b9ca4a;">:diffupdate<</span>CR<span style="color:#c397d8;">></span> map <span style="color:#b9ca4a;"><silent></span> <span style="color:#c397d8;"><</span>leader<span style="color:#c397d8;">></span>3 <span style="color:#b9ca4a;">:diffget </span>3<span style="color:#c397d8;"><</span>CR<span style="color:#c397d8;">></span> <span style="color:#b9ca4a;">:diffupdate<</span>CR<span style="color:#c397d8;">></span> map <span style="color:#b9ca4a;"><silent></span> <span style="color:#c397d8;"><</span>leader<span style="color:#c397d8;">></span>4 <span style="color:#b9ca4a;">:diffget </span>4<span style="color:#c397d8;"><</span>CR<span style="color:#c397d8;">></span> <span style="color:#b9ca4a;">:diffupdate<</span>CR<span style="color:#c397d8;">></span>
",2" ",3" ",4" to pull change from top three buffer. The bottom buffer is for editing the code with markers which is actually your only work space.
":help vimdiff" for other hot keys.