Reputation: 13913
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?
Upvotes: 11
Views: 2736
Reputation: 1330102
The Documentation/mergetools/vimdiff.txt
recently (2022) documented:
In addition, for backwards compatibility with previous Git versions, you can also append
1
,2
or3
to eithervimdiff
or any of the variants (ex:vimdiff3
,nvimdiff1
, etc...) to use a predefined layout.In other words, using
--tool=[g,n,]vimdiffx
is the same as using--tool=[g,n,]vimdiff
and setting configuration variablemergetool.[g,n,]vimdiff.layout
to...
x=1
:"@LOCAL, REMOTE"
x=2
:"LOCAL, MERGED, REMOTE"
x=3
:"MERGED"
Example: using
--tool=gvimdiff2
will opengvim
with three columns (LOCAL
,MERGED
andREMOTE
).
This should work better with Git 2.37.3 (Q3 2022), which does fix a "vimdiff3
" regression.
See commit 34133d9, commit b6014ee, commit ffcc33f, commit 60184ab, commit 66dd83a, commit 79db50d, commit d619183 (10 Aug 2022) by Felipe Contreras (felipec
).
(Merged by Junio C Hamano -- gitster
-- in commit 4d8074b, 18 Aug 2022)
mergetools
: vimdiff: fix single window layoutsCc: Fernando Ramos
Signed-off-by: Felipe Contreras
Reviewed-by: Fernando Ramos
Layouts with a single window other than "
MERGED
" do not work (e.g. "LOCAL
" or "MERGED+LOCAL
").This is because as the documentation of
bufdo
says:The last buffer (or where an error occurred) becomes the current buffer.
And we do always do
bufdo
the end.Additionally, we do it only once, when it should be per tab.
Fix this by doing it once per tab right after it's created and before any buffer is switched.
Upvotes: 1
Reputation: 13913
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.
Upvotes: 9