When I run git difftool --tool-help
or git mergetool --tool-help
, I see:
vimdiff
vimdiff1
vimdiff2
vimdiff3
What are these different "versions"? I assume they all start Vim with different options, but what are the options? Are they documented anywhere?
They don't seem to be documented anywhere, unfortunately.
The relevant source code is here. Note how vimdiff
, nvimdiff
, and gvimdiff
are all implemented with the same script.
When invoked as a difftool, they all do the same thing:
vim -R -f -d \
-c 'wincmd l' \
-c 'cd $GIT_PREFIX' \
"$LOCAL" "$REMOTE"
This starts Vim in read-only mode -R
and diff mode -d
. For information on diff mode, see the manpage vimdiff(1)
and the Vim help page diff.txt
.
When invoked as a mergetool, the behavior of these options varies.
In the diagrams below, Local
corresponds to "ours", Remote
corresponds to "theirs", Base
corresponds to "merge base", and Merge
is the file that will actually be saved to the work tree (and staged to the index if the resolution is successful).
vimdiff
If there is a "merge base" present, the window layout is:
# | Local | Base | Remote |
# | --------------------- |
# | Merge |
vim -f -d \
-c '4wincmd w | wincmd J' \
"$LOCAL" "$BASE" "$REMOTE" "$MERGED"
If there is not a merge base present, the layout is:
# | | | |
# | Local | Merge | Remote |
# | | | |
vim -f -d \
-c 'wincmd l' \
"$LOCAL" "$MERGED" "$REMOTE"
vimdiff1
The layout is:
# | | |
# | Local | Remote |
# | | |
vim -f -d "$LOCAL" "$REMOTE"
ret="$?"
if test "$ret" -eq 0
then
cp -- "$LOCAL" "$MERGED"
fi
Local
will then be saved to the work tree upon success, taking the place of Merged
.
vimdiff2
The layout is identical to vimdiff
without a merge base.
vimdiff3
Each of Local
, Remote
, Base
(if present) will be opened but hidden. Merged
will be opened and visible. You can switch among these buffers with the :buffer
command.
# With Base
vim -f -d \
-c 'hid | hid | hid' \
"$LOCAL" "$REMOTE" "$BASE" "$MERGED"
# Without Base
vim -f -d \
-c 'hid | hid' \
"$LOCAL" "$REMOTE" "$MERGED"
Let's create a vimdiff4
, which uses the same layout as vimdiff
-with-Base, but omitting the Base part.
Add the following to your Git config (e.g. $XDG_CONFIG_HOME/git/config
):
[mergetool "nvimdiff4"]
# Like "nvimdiff", but always ignore $BASE.
cmd = nvim -f -d -c '$wincmd w' -c 'wincmd J' $LOCAL $REMOTE $MERGED
When you invoke git mergetool --tool-help
, you will see a new line in the output:
user-defined:
nvimdiff4.cmd nvim -d -c '$wincmd w' -c 'wincmd J' $LOCAL $REMOTE $MERGED
Now you can run git mergetool --tool=nvimdiff4
, which will invoke the command we specified above.