A lot has been written about plugins like Fugitive.vim that help you use Git from within Vim. Here I'm going to be looking at it from the other side; how can Vim help with common Git tasks? I'll start with how to set Vim as the default editor for Git, move on to Git's built-in support for viewing diffs and resolving merge conflicts using Vim and GVim, and then finally look at how Git's built in tools can be configured to use MacVim or any other tool you like.
The basics: Setting Git's default editor
The most basic level of integration is using Vim for Git commands that launch
an editor, commands like
Git determines which editor to use by checking its own configuration first
$GIT_EDITOR environment variable, and then the
core.editor configuration variable), but if they're not set it
falls back to the standard UNIX environment variables (
$EDITOR), before finally defaulting to
$VISUAL editor is set to MacVim, but I prefer to use plain
old Vim for Git commands so I don't have to leave the terminal I'm working
in. Git prefers
$EDITOR, so I override
the default behaviour by setting Git's
variable. Set it using the
git config command:
$ git config --global core.editor `which vim`
The --global flag indicates that this change should apply to all repositories, if you omit this flag and issue the command from a directory that is a Git repository then the setting will only apply to that one repository.
Diff and merge with Vim
Vim's diff mode
One of the things I was delighted to discover when I switched from TextMate to Vim was Vim's powerful diff mode.
You can launch Vim in diff mode with vim -d file1
file2 or vimdiff file1
work, if you're using GVim or MacVim respectively). When you do, you are
presented with a Vim session split vertically into multiple windows, each
showing one of the files you specified at the command line with the
As you scroll around and make changes in any one of the windows, the other
windows scroll and update in real time, so you're always seeing accurate and
up-to-date diff information right next to the line you're editing.
This seemed like the perfect tool for viewing Git diffs, and resolving
merge conflicts so I did a little research and came across two Git
commands I hadn't previously encountered:
git difftool is very similar to
git diff and
supports the same parameters, the difference is that the results aren't
printed to the standard output, instead they're sent to a specialised diff
git mergetool is used to resolve merge conflicts by sending
each conflicted file in turn to a specialised conflict resolution tool.
Both of these commands support a variety of tools, including
opendiff (which isn't directly relevant to a discussion of
using Git with Vim, but on OS X will launch the excellent
utility) and of course
You can specify which tool to use with the -t parameter, for
$ git difftool -t vimdiff
If you don't want to specify the tool to use every time you can set Git's
merge.tool configuration variables:
$ git config --global merge.tool vimdiff $ git config --global diff.tool vimdiff
While you're there, you might also want to suppress the Hit return to launch 'vimdiff' prompt:
$ git config --global mergetool.prompt false $ git config --global difftool.prompt false
There are some additional options for both tools that I find useful. First
git difftool allows you to specify a second, GUI based
tool using the
diff.guitool variable. You can use the GUI
tool by invoking
git difftool with the -g option.
vimdiff as my
diff.tool and MacVim as my
diff.guitool (there's more on how to use MacVim later).
Secondly, by default
git mergetool will create a backup copy
of whichever files you're merging. You can remove these manually when you're
finished with either
git clean or plain old
if you want
git mergetool to clean up after itself you can set
mergetool.keepBackup option to
git mergetool and
git difftool both have
baked in support for Vim and GVim, they don't support MacVim without a little
The quick fix
The easiest way to use MacVim is just to edit Git's
path so it points to the
mvimdiff binary instead:
$ git config --global difftool.gvimdiff.path `which mvimdiff` $ git config --global mergetool.gvimdiff.path `which mvimdiff`
Now you can set the
diff.guitool variables to
gvimdiff, or use the
-t gvimdiff argument, and Git will launch MacVim instead of GVim.
A custom mergetool
If you want to customise things further, and not just modify the executable
git mergetool calls, but also change the parameters, you
will need to define a custom mergetool.
You can do this from the command line using
git config, but
I think it's easier to do this kind of complex configuration by editing your
Git config file directly. For global settings you can edit
~/.gitconfig, or for a specific project edit
.git/config from the repository's root directory.
Add the following to your Git config file:
[mergetool "toolname"] cmd = command
You can then use your custom toolname with the -t
option or in the
The following variables are available to use in your command, each is the path to a particular version of the file that is being merged:
This is the version of the file that you should edit; it is the version of
the file in your working copy of the repository, so it's what you would be
editing anyway if you were resolving a merge conflict without the help
- This is the file as it was on your local branch before you started the merge.
- This is the file as it is on the remote branch, that is the branch you are merging into your local branch.
- This is the base of the merge, that is the file as it was before the two branches introduced incompatible changes.
For example, my MacVim configuration looks like this:
[mergetool "mvimdiff"] cmd = /usr/local/bin/mvimdiff -f "$LOCAL" "$MERGED" "$REMOTE"
Note the -f flag; this tells MacVim to run in the foreground.
When you close your chosen tool
git mergetool will stage the
file for you if you've made changes, or will prompt you to stage it with the
question filename seems unchanged. Was the merge
successful? In either case, you can still make further
changes before you commit,
mergetool only stages your changes,
it doesn't commit them. Without the -f flag you can't take
advantage of this behaviour.
A custom difftool
The configuration for a custom difftool is very similar. As with a custom mergetool, you add the following to your Git config file:
[difftool "toolname"] cmd = command
You can use your custom toolname in either the -t
option, or the
The command can contain all of the same variables as a mergetool command,
although in this case
$MERGED will both
contain the path of the current working version.
Copy and paste
Here are some edited highlights from my
which capture most of the configuration options discussed above. You may
need to change some paths for this to work on your system.
[core] editor = /usr/bin/vim [mergetool "mvimdiff"] cmd = /usr/local/bin/mvimdiff -f "$LOCAL" "$MERGED" "$REMOTE" [merge] tool = mvimdiff [mergetool] prompt = false keepBackup = false [difftool "gvimdiff"] path = /usr/local/bin/mvimdiff [diff] tool = vimdiff guitool = gvimdiff [difftool] prompt = false