Use Vim as git diff and merge tool
01 Jan 2025 - John Z. Li
When working on remote servers, GUI-based diff and merge tools are uaually
a luxury we cannot afford. In such a situation, vim is often what we can rely
on, because it is installed by default by almost all distributions.
It is useful to learn how to do git diff and git merge from terminal with only
vim.
Configuration
- Put the following in
.bashrc, so thatvimdiffalways uses thevimfound in$PATH, instead of thevimdiffcommand in$PATH.alias vimdiff="vim -d"This is needed because
vimdiffopens files in readonly mode by default, This is usually what one needs. if a file is already opened in readonly mode, one can use:set noroto enable editing insidevim.) - Put the following in
.gitconfig:[diff] tool = vimdiff [difftool] prompt = false [merge] tool = vimdiff conflictstyle = diff3 [mergetool] prompt = false
Invoke vimdiff from command line.
- Compare two or more files
vimdiff file1 file2 [file3 [file4]]If you are already in
vim, and you want compare the current buffer with another file::diffsplit [filename] # same as diffs : vert diffsplit [filename] # same as above but windows are vertically splitted. # The below command set the current window part of the diff windows, as if the # window is opened with `vimdiff`. :diffthis # same as difftWhen you are done, use
diffoffordiffoff!to switch off diff-mode. The former disables diff mode in the current window, the latter disables diff mode in all the windows under the current Tab. - Jump between diff-conflictstyle
- Use
[cto jump to the previous diff-conflict. - Use
]cto jump to the next diff-conflict.
- Use
- Dealing with diff-conflicts
:[range] diffget [bufspec], or:diffgwhen dealing with the current diff-conflict and with only two files. This modifies the current buffer to remove difference against another buffer.:[range] diffput [bufspec], ordiffpuwhen dealing with the current diff-conflict and with only two files, This modifies other buffers to remove difference againt the current buffer.do, same as:diffgetwithout range or bufspec,ostands for obtain.dp, same as:diffputwithout range or bufspec,pstands for put.
- Re-synchronize diff-view
If diff-view is out-of-sync, use
:diffupdateor:diffuto
Start vimdiff from git
- Compare a file with staged or unstaged changes:
git difftool [<filename>*] - Compare a file with the the N-commit-before version of the same file
# show all changed files between head 1-commit before git diff --name-only HEAD^ HEAD # like --name-only but has modifier charactor to indicated what # has happened to the file git diff --name-status HEAD^ HEAD # see file change history git log --name-status --oneline # the following syntax is equivalent, # but with 2-commit before and file names git difftool HEAD^^ HEAD [<filename>*] git difftool HEAD^^..HEAD -- [<filename>*] git difftool HEAD~2 HEAD -- [<filename>*] - Compare a file with the specific commit version of the same
file
# spceify tag name git difftool tagname HEAD -- [<filename>*] git difftool tagname..HEAD -- [<filename>*] # specify commits by commit-has git difftool [commit-hash1] [commit-hash2] -- [<filename>*] git difftool [commit-hash1]..[commit-hash2] -- [<filename>*] - Compare a file across diffrent branch
git difftool [branch1] [branch2] -- [filename] git difftool [branch1]..[branch2] -- [filename]
Use git mergetool to solve merge conflict
When there is a merge conflict,
- Use
git mergetoolto lauch vim in merge mode. - From the left to right, three windows are
- ‘LOCAL’, the merged-to branch
- ‘BASE’, common acestor
- ‘REMOTE’, the merged-from branch
- The bottom window is mergeconflict file in
diff3format. The mergeconflict file is the file we will commit when all conflicts are solved.
- We can use
]cand[cto jump forward and backward on the merge conflict file. - Use the following to select which change is applied to the merged file:
:diffget REor:diffg REto select change from ‘REMOTE’.:diffget BAor:diffg BAto select change from ‘BASE’.:diffget LOor:diffg LOto select change from ‘LOCAL’
Invoke git tools from vim using tools like vim-fugitive
:Git diffto check staged or unstaged changes of the current file.:Git difftoolworks like:Git diffbut put differences in a quickfix window. (not very useful).:Gvsplit HEAD~3:%to open the version of this file 3-commit-ago in a vertically split window.:Gedit HEAD~3:%andGsplit HEAD~3:%do the same but current window or horizontal new window.:Gvdiffsplitto compare the current file with the staged version of the same file.:Git mergetoolis broken.