diff mbox series

[v7,3/4] vimdiff: add tool documentation

Message ID 20220328223019.271270-4-greenfoo@u92.eu (mailing list archive)
State Superseded
Headers show
Series vimdiff: new implementation with layout support | expand

Commit Message

Fernando Ramos March 28, 2022, 10:30 p.m. UTC
Running 'git {merge,diff}tool --tool-help' now also prints usage
information about the vimdiff tool (and its variantes) instead of just
its name.

Two new functions ('diff_cmd_help()' and 'merge_cmd_help()') have been
added to the set of functions that each merge tool (ie. scripts found
inside "mergetools/") can overwrite to provided tool specific
information.

Right now, only 'mergetools/vimdiff' implements these functions, but
other tools are encouraged to do so in the future, specially if they
take configuration options not explained anywhere else (as it is the
case with the 'vimdiff' tool and the new 'layout' option)

In addition, a section has been added to
"Documentation/git-mergetool.txt" to explain the new "layout"
configuration option with examples.

Signed-off-by: Fernando Ramos <greenfoo@u92.eu>
Signed-off-by: Philippe Blain <levraiphilippeblain@gmail.com>
---
 Documentation/config/mergetool.txt   |   9 ++
 Documentation/git-mergetool.txt      |   8 ++
 Documentation/mergetools/vimdiff.txt | 189 +++++++++++++++++++++++++++
 git-mergetool--lib.sh                |  10 +-
 mergetools/vimdiff                   |  53 ++++++++
 5 files changed, 268 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/mergetools/vimdiff.txt

Comments

Fernando Ramos March 28, 2022, 10:39 p.m. UTC | #1
When applying this patch I still get "indent with spaces" errors:

    .git/rebase-apply/patch:121: indent with spaces.
               ------------------------------------------
    .git/rebase-apply/patch:122: indent with spaces.
               |             |           |              |
    .git/rebase-apply/patch:123: indent with spaces.
               |             |           |              |
    .git/rebase-apply/patch:124: indent with spaces.
               |   LOCAL     |   MERGED  |   REMOTE     |
    .git/rebase-apply/patch:125: indent with spaces.
               |             |           |              |
    warning: squelched 61 whitespace errors
    warning: 66 lines add whitespace errors.

The thing is these are no real errors (I really want to use spaces here).

Am I doing something wrong?
Junio C Hamano March 29, 2022, 1:01 a.m. UTC | #2
Fernando Ramos <greenfoo@u92.eu> writes:

> When applying this patch I still get "indent with spaces" errors:
>
>     .git/rebase-apply/patch:121: indent with spaces.
>                ------------------------------------------
>     .git/rebase-apply/patch:122: indent with spaces.
>                |             |           |              |
>     .git/rebase-apply/patch:123: indent with spaces.
>                |             |           |              |
>     .git/rebase-apply/patch:124: indent with spaces.
>                |   LOCAL     |   MERGED  |   REMOTE     |
>     .git/rebase-apply/patch:125: indent with spaces.
>                |             |           |              |
>     warning: squelched 61 whitespace errors
>     warning: 66 lines add whitespace errors.
>
> The thing is these are no real errors (I really want to use spaces here).
>
> Am I doing something wrong?

Yes, the project does not want you to use spaces here.  Doesn't
AsciiDoc do the right thing if you used a tab instead of indenting
with 8 spaces?
Philippe Blain March 29, 2022, 2:07 p.m. UTC | #3
Hi Fernando,

Le 2022-03-28 à 18:30, Fernando Ramos a écrit :
> Running 'git {merge,diff}tool --tool-help' now also prints usage
> information about the vimdiff tool (and its variantes) instead of just
> its name.
> 
> Two new functions ('diff_cmd_help()' and 'merge_cmd_help()') have been
> added to the set of functions that each merge tool (ie. scripts found
> inside "mergetools/") can overwrite to provided tool specific
> information.
> 
> Right now, only 'mergetools/vimdiff' implements these functions, but
> other tools are encouraged to do so in the future, specially if they
> take configuration options not explained anywhere else (as it is the
> case with the 'vimdiff' tool and the new 'layout' option)
> 
> In addition, a section has been added to
> "Documentation/git-mergetool.txt" to explain the new "layout"
> configuration option with examples.
> 
> Signed-off-by: Fernando Ramos <greenfoo@u92.eu>
> Signed-off-by: Philippe Blain <levraiphilippeblain@gmail.com>

Thanks :) I think the project convention is to also use the 
'Co-authored-by' trailer as well :) 

> ---
>  Documentation/config/mergetool.txt   |   9 ++
>  Documentation/git-mergetool.txt      |   8 ++
>  Documentation/mergetools/vimdiff.txt | 189 +++++++++++++++++++++++++++
>  git-mergetool--lib.sh                |  10 +-
>  mergetools/vimdiff                   |  53 ++++++++
>  5 files changed, 268 insertions(+), 1 deletion(-)
>  create mode 100644 Documentation/mergetools/vimdiff.txt
> 
> diff --git a/Documentation/config/mergetool.txt b/Documentation/config/mergetool.txt
> index cafbbef46a..13f1b234db 100644
> --- a/Documentation/config/mergetool.txt
> +++ b/Documentation/config/mergetool.txt
> @@ -45,6 +45,15 @@ mergetool.meld.useAutoMerge::
>  	value of `false` avoids using `--auto-merge` altogether, and is the
>  	default value.
>  
> +mergetool.vimdiff.layout::
> +	The vimdiff backend uses this variable to control how its split
> +	windows look like. Applies even if you are using Neovim (`nvim`) or
> +	gVim (`gvim`) as the merge tool. See BACKEND SPECIFIC HINTS section
> +ifndef::git-mergetool[]
> +	(on linkgit:git-mergetool[1])

small nit: "in linkgit:git-mergetool[1]" would read slightly better I think,
but that may be just me... and I think I would drop the parentheses.

> +endif::[]
> +	for details.
> +

> diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
> index 542a6a75eb..9f99201bcc 100644
> --- a/git-mergetool--lib.sh
> +++ b/git-mergetool--lib.sh
> @@ -63,7 +63,7 @@ $(list_tool_variants)"
>  					preamble=
>  				fi
>  				shown_any=yes
> -				printf "%s%s\n" "$per_line_prefix" "$toolname"
> +				printf "%s%-15s  %s\n" "$per_line_prefix" "$toolname" $(diff_mode && diff_cmd_help "$toolname" || merge_cmd_help "$toolname")
>  			fi

I tried this and it looks much better on a single line, nice!

I also noticed that the list of available tools is embedded in 'git help config'
(see the rule for "mergetools-list.made" in Documentation/Makefile). I looked 
at the generated 'git-config.html' and it is not ideal; it would be better if 
the tool names would be enclosed in backticks. I tried the following tweak:

diff --git a/Documentation/Makefile b/Documentation/Makefile
index ed656db2ae..a2201680a2 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -333,10 +333,10 @@ mergetools-list.made: ../git-mergetool--lib.sh $(wildcard ../mergetools/*)
 	$(QUIET_GEN) \
 	$(SHELL_PATH) -c 'MERGE_TOOLS_DIR=../mergetools && \
 		. ../git-mergetool--lib.sh && \
-		show_tool_names can_diff "* " || :' >mergetools-diff.txt && \
+		show_tool_names can_diff "* " || :' | sed -e "s/* \([a-z0-9]*\)/* \`\1\`:/" >mergetools-diff.txt && \
 	$(SHELL_PATH) -c 'MERGE_TOOLS_DIR=../mergetools && \
 		. ../git-mergetool--lib.sh && \
-		show_tool_names can_merge "* " || :' >mergetools-merge.txt && \
+		show_tool_names can_merge "* " || :' | sed -e "s/* \([a-z0-9]*\)/* \`\1\`:/" >mergetools-merge.txt && \
 	date >$@
 
 TRACK_ASCIIDOCFLAGS = $(subst ','\'',$(ASCIIDOC_COMMON):$(ASCIIDOC_HTML):$(ASCIIDOC_DOCBOOK))


and it mostly works, though with the Asciidoc HTML backend, "emerge" is not correctly
formatted, I get:

‘emerge`: Use Emacs’ Emerge

and in the man page the backticks are kept litereally.It works correctly 
with Asciidoctor though, both in HTML and man page ...
Junio C Hamano March 29, 2022, 4:35 p.m. UTC | #4
Philippe Blain <levraiphilippeblain@gmail.com> writes:

>> Running 'git {merge,diff}tool --tool-help' now also prints usage
>> information about the vimdiff tool (and its variantes) instead of just
>> its name.
>> 
>> Two new functions ('diff_cmd_help()' and 'merge_cmd_help()') have been
>> added to the set of functions that each merge tool (ie. scripts found
>> inside "mergetools/") can overwrite to provided tool specific
>> information.
>> 
>> Right now, only 'mergetools/vimdiff' implements these functions, but
>> other tools are encouraged to do so in the future, specially if they
>> take configuration options not explained anywhere else (as it is the
>> case with the 'vimdiff' tool and the new 'layout' option)
>> 
>> In addition, a section has been added to
>> "Documentation/git-mergetool.txt" to explain the new "layout"
>> configuration option with examples.
>> 
>> Signed-off-by: Fernando Ramos <greenfoo@u92.eu>
>> Signed-off-by: Philippe Blain <levraiphilippeblain@gmail.com>
>
> Thanks :) I think the project convention is to also use the 
> 'Co-authored-by' trailer as well :) 

If co-authors closely worked together (possibly but not necessarily
outside the public view), exchanging drafts and agreeing on the
final version before sending it to the list, by one approving the
other's final draft, Co-authored-by may be appropriate.

I am not sure if that is what happened.

I would prefer to see more use of Helped-by when suggestions for
improvements were made, possibly but not necessarily in a concrete
"squashable patch" form, the original author accepted before sending
the new version out, and the party who made suggestions saw the
updated version at the same time as the general public.

In addition, especially if it was not co-authored, the chain of
sign-off should mirror how the patches flowed.  If philippe helped
to improve Fernando's original idea, and Fernando assembled this
version before sending it out to the list, then 

    Helped-by: Philippe
    Signed-off-by: Philippe
    Signed-off-by: Fernando

Philippe's sign-off would help when his contribution is so big that
it by itself makes a copyrightable work, which may be the case.  If
not (e.g. when pointing out trivial typo or grammo), it is simpler
to omit it.

If this were truly co-authored, then replace "Helped-by" in the
above sequence with "Co-authored-by".

>> +mergetool.vimdiff.layout::
>> +	The vimdiff backend uses this variable to control how its split
>> +	windows look like. Applies even if you are using Neovim (`nvim`) or
>> +	gVim (`gvim`) as the merge tool. See BACKEND SPECIFIC HINTS section
>> +ifndef::git-mergetool[]
>> +	(on linkgit:git-mergetool[1])
>
> small nit: "in linkgit:git-mergetool[1]" would read slightly better I think,
> but that may be just me... and I think I would drop the parentheses.

I agree on both counts.

>>  				shown_any=yes
>> -				printf "%s%s\n" "$per_line_prefix" "$toolname"
>> +				printf "%s%-15s  %s\n" "$per_line_prefix" "$toolname" $(diff_mode && diff_cmd_help "$toolname" || merge_cmd_help "$toolname")
>>  			fi
>
> I tried this and it looks much better on a single line, nice!

You mean that the output on a single line is better than multiple lines?

> I also noticed that the list of available tools is embedded in 'git help config'
> (see the rule for "mergetools-list.made" in Documentation/Makefile). I looked 
> at the generated 'git-config.html' and it is not ideal; it would be better if 
> the tool names would be enclosed in backticks. I tried the following tweak:
>
> diff --git a/Documentation/Makefile b/Documentation/Makefile
> index ed656db2ae..a2201680a2 100644
> --- a/Documentation/Makefile
> +++ b/Documentation/Makefile
> @@ -333,10 +333,10 @@ mergetools-list.made: ../git-mergetool--lib.sh $(wildcard ../mergetools/*)
>  	$(QUIET_GEN) \
>  	$(SHELL_PATH) -c 'MERGE_TOOLS_DIR=../mergetools && \
>  		. ../git-mergetool--lib.sh && \
> -		show_tool_names can_diff "* " || :' >mergetools-diff.txt && \
> +		show_tool_names can_diff "* " || :' | sed -e "s/* \([a-z0-9]*\)/* \`\1\`:/" >mergetools-diff.txt && \

If you are piping the output into a sed command, then you discard
the exit status of the upstream of the pipe, so " || :" at the end
of the shell command can be discarded, no?

>  	$(SHELL_PATH) -c 'MERGE_TOOLS_DIR=../mergetools && \
>  		. ../git-mergetool--lib.sh && \
> -		show_tool_names can_merge "* " || :' >mergetools-merge.txt && \
> +		show_tool_names can_merge "* " || :' | sed -e "s/* \([a-z0-9]*\)/* \`\1\`:/" >mergetools-merge.txt && \
>  	date >$@

Ditto.

In any case, the raw output from the command are of the form

    * <name of the tool> <explanation>

Is the idea that you want to enclose the <name of the tool> part
inside `literal`?

I do not know if the inclusion of <explanation> part in the output
is sensible in the first place (without this series, we only showed
the possible values, right), but if we wanted to do this, shouldn't
we be doing, instead of doing

    * araxis	Use Araxis Merge

more like

    araxis;;
		Use Araxis

I wonder.  The logical structure of each line is unclear with the
current output (the asterisk is meaningful in that it tells that the
line is an item in a bulleted list, but among the words on the rest
of the line, the first line is special only by convention, so in a
manpage for example, it looks like a gramatically correct sentence
"Use Araxis Merge" is somehow prefixed by a stray word that does not
begin with uppercase).
Philippe Blain March 29, 2022, 5:08 p.m. UTC | #5
Hi Junio,

Le 2022-03-29 à 12:35, Junio C Hamano a écrit :
> Philippe Blain <levraiphilippeblain@gmail.com> writes:
> 
>>> Running 'git {merge,diff}tool --tool-help' now also prints usage
>>> information about the vimdiff tool (and its variantes) instead of just
>>> its name.
>>>
>>> Two new functions ('diff_cmd_help()' and 'merge_cmd_help()') have been
>>> added to the set of functions that each merge tool (ie. scripts found
>>> inside "mergetools/") can overwrite to provided tool specific
>>> information.
>>>
>>> Right now, only 'mergetools/vimdiff' implements these functions, but
>>> other tools are encouraged to do so in the future, specially if they
>>> take configuration options not explained anywhere else (as it is the
>>> case with the 'vimdiff' tool and the new 'layout' option)
>>>
>>> In addition, a section has been added to
>>> "Documentation/git-mergetool.txt" to explain the new "layout"
>>> configuration option with examples.
>>>
>>> Signed-off-by: Fernando Ramos <greenfoo@u92.eu>
>>> Signed-off-by: Philippe Blain <levraiphilippeblain@gmail.com>
>>
>> Thanks :) I think the project convention is to also use the 
>> 'Co-authored-by' trailer as well :) 
> 
> If co-authors closely worked together (possibly but not necessarily
> outside the public view), exchanging drafts and agreeing on the
> final version before sending it to the list, by one approving the
> other's final draft, Co-authored-by may be appropriate.
> 
> I am not sure if that is what happened.
> 
> I would prefer to see more use of Helped-by when suggestions for
> improvements were made, possibly but not necessarily in a concrete
> "squashable patch" form, the original author accepted before sending
> the new version out, and the party who made suggestions saw the
> updated version at the same time as the general public.
> 
> In addition, especially if it was not co-authored, the chain of
> sign-off should mirror how the patches flowed.  If philippe helped
> to improve Fernando's original idea, and Fernando assembled this
> version before sending it out to the list, then 
> 
>     Helped-by: Philippe
>     Signed-off-by: Philippe
>     Signed-off-by: Fernando
> 
> Philippe's sign-off would help when his contribution is so big that
> it by itself makes a copyrightable work, which may be the case.  If
> not (e.g. when pointing out trivial typo or grammo), it is simpler
> to omit it.
> 
> If this were truly co-authored, then replace "Helped-by" in the
> above sequence with "Co-authored-by".

Thanks for clarifying all that (whatever happened to the "Mailing
list etiquette series [1]... it would be nice to revive this:).

I did not mean to "claim" co-authorship by the way, I agree that 
"Helped-by" is more appropriate in this case. I included my sign-off
mostly by accident as my 'ci' Git alias in this project is 'commit --sign-off' ;)

> 
>>> +mergetool.vimdiff.layout::
>>> +	The vimdiff backend uses this variable to control how its split
>>> +	windows look like. Applies even if you are using Neovim (`nvim`) or
>>> +	gVim (`gvim`) as the merge tool. See BACKEND SPECIFIC HINTS section
>>> +ifndef::git-mergetool[]
>>> +	(on linkgit:git-mergetool[1])
>>
>> small nit: "in linkgit:git-mergetool[1]" would read slightly better I think,
>> but that may be just me... and I think I would drop the parentheses.
> 
> I agree on both counts.
> 
>>>  				shown_any=yes
>>> -				printf "%s%s\n" "$per_line_prefix" "$toolname"
>>> +				printf "%s%-15s  %s\n" "$per_line_prefix" "$toolname" $(diff_mode && diff_cmd_help "$toolname" || merge_cmd_help "$toolname")
>>>  			fi
>>
>> I tried this and it looks much better on a single line, nice!
> 
> You mean that the output on a single line is better than multiple lines?

Yes.

> 
>> I also noticed that the list of available tools is embedded in 'git help config'
>> (see the rule for "mergetools-list.made" in Documentation/Makefile). I looked 
>> at the generated 'git-config.html' and it is not ideal; it would be better if 
>> the tool names would be enclosed in backticks. I tried the following tweak:
>>
>> diff --git a/Documentation/Makefile b/Documentation/Makefile
>> index ed656db2ae..a2201680a2 100644
>> --- a/Documentation/Makefile
>> +++ b/Documentation/Makefile
>> @@ -333,10 +333,10 @@ mergetools-list.made: ../git-mergetool--lib.sh $(wildcard ../mergetools/*)
>>  	$(QUIET_GEN) \
>>  	$(SHELL_PATH) -c 'MERGE_TOOLS_DIR=../mergetools && \
>>  		. ../git-mergetool--lib.sh && \
>> -		show_tool_names can_diff "* " || :' >mergetools-diff.txt && \
>> +		show_tool_names can_diff "* " || :' | sed -e "s/* \([a-z0-9]*\)/* \`\1\`:/" >mergetools-diff.txt && \
> 
> If you are piping the output into a sed command, then you discard
> the exit status of the upstream of the pipe, so " || :" at the end
> of the shell command can be discarded, no?

Yes, you are right.

> 
>>  	$(SHELL_PATH) -c 'MERGE_TOOLS_DIR=../mergetools && \
>>  		. ../git-mergetool--lib.sh && \
>> -		show_tool_names can_merge "* " || :' >mergetools-merge.txt && \
>> +		show_tool_names can_merge "* " || :' | sed -e "s/* \([a-z0-9]*\)/* \`\1\`:/" >mergetools-merge.txt && \
>>  	date >$@
> 
> Ditto.
> 
> In any case, the raw output from the command are of the form
> 
>     * <name of the tool> <explanation>
> 
> Is the idea that you want to enclose the <name of the tool> part
> inside `literal`?

Yes, exactly, and add ': ' after the name of the tool. This makes the
HTML doc for 'git-config' more nicely formatted.

> 
> I do not know if the inclusion of <explanation> part in the output
> is sensible in the first place (without this series, we only showed
> the possible values, right), 

Right. I think it is a very nice addition, as several mergetool "names"
are not the same as the program name or the executable name, so I think
it's nice for the user to spell out exactly which software we are refering
to :) 

> but if we wanted to do this, shouldn't
> we be doing, instead of doing
> 
>     * araxis	Use Araxis Merge
> 
> more like
> 
>     araxis;;
> 		Use Araxis
> 
> I wonder.  The logical structure of each line is unclear with the
> current output (the asterisk is meaningful in that it tells that the
> line is an item in a bulleted list, but among the words on the rest
> of the line, the first line is special only by convention, so in a
> manpage for example, it looks like a gramatically correct sentence
> "Use Araxis Merge" is somehow prefixed by a stray word that does not
> begin with uppercase).
> 

OK, I see you mean using an Asciidoc "description list" [2]. I agree 
with you that it would be more semantically correct. So, let's use this
instead:

diff --git a/Documentation/Makefile b/Documentation/Makefile
index ed656db2ae..de0b5fed42 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -333,10 +333,10 @@ mergetools-list.made: ../git-mergetool--lib.sh $(wildcard ../mergetools/*)
 	$(QUIET_GEN) \
 	$(SHELL_PATH) -c 'MERGE_TOOLS_DIR=../mergetools && \
 		. ../git-mergetool--lib.sh && \
-		show_tool_names can_diff "* " || :' >mergetools-diff.txt && \
+		show_tool_names can_diff' | sed -e "s/\([a-z0-9]*\)/\`\1\`;;/" >mergetools-diff.txt && \
 	$(SHELL_PATH) -c 'MERGE_TOOLS_DIR=../mergetools && \
 		. ../git-mergetool--lib.sh && \
-		show_tool_names can_merge "* " || :' >mergetools-merge.txt && \
+		show_tool_names can_merge' | sed -e "s/\([a-z0-9]*\)/\`\1\`;;/" >mergetools-merge.txt && \
 	date >$@
 
 TRACK_ASCIIDOCFLAGS = $(subst ','\'',$(ASCIIDOC_COMMON):$(ASCIIDOC_HTML):$(ASCIIDOC_DOCBOOK))

[1] https://lore.kernel.org/git/20210512233412.10737-1-dwh@linuxprogrammer.org/
[2] https://docs.asciidoctor.org/asciidoc/latest/lists/description/
Philippe Blain March 29, 2022, 5:29 p.m. UTC | #6
Hi Fernando,

Le 2022-03-28 à 18:30, Fernando Ramos a écrit :
> +
> diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
> index 542a6a75eb..9f99201bcc 100644
> --- a/git-mergetool--lib.sh
> +++ b/git-mergetool--lib.sh
> @@ -63,7 +63,7 @@ $(list_tool_variants)"
>  					preamble=
>  				fi
>  				shown_any=yes
> -				printf "%s%s\n" "$per_line_prefix" "$toolname"
> +				printf "%s%-15s  %s\n" "$per_line_prefix" "$toolname" $(diff_mode && diff_cmd_help "$toolname" || merge_cmd_help "$toolname")
>  			fi
>  		done
>  

While responding to Junio I tried removing the definition of
'diff_cmd_help' for araxis and it is still listed as "Use Araxis"
in the list of values under "merge.guitool" in git-config.{1,html}.

I think that "diff_mode" that you use in the command substitution does
not work for our usage in the documentation Makefile, as in that case
TOOL_MODE is not defined. So a more complete tweak to the Makefile
would be:

diff --git a/Documentation/Makefile b/Documentation/Makefile
index ed656db2ae..c2667de7b3 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -331,12 +331,12 @@ $(mergetools_txt): mergetools-list.made
 
 mergetools-list.made: ../git-mergetool--lib.sh $(wildcard ../mergetools/*)
 	$(QUIET_GEN) \
-	$(SHELL_PATH) -c 'MERGE_TOOLS_DIR=../mergetools && \
+	$(SHELL_PATH) -c 'MERGE_TOOLS_DIR=../mergetools && TOOL_MODE=diff && \
 		. ../git-mergetool--lib.sh && \
-		show_tool_names can_diff "* " || :' >mergetools-diff.txt && \
-	$(SHELL_PATH) -c 'MERGE_TOOLS_DIR=../mergetools && \
+		show_tool_names can_diff' | sed -e "s/\([a-z0-9]*\)/\`\1\`;;/" >mergetools-diff.txt && \
+	$(SHELL_PATH) -c 'MERGE_TOOLS_DIR=../mergetools && TOOL_MODE=merge && \
 		. ../git-mergetool--lib.sh && \
-		show_tool_names can_merge "* " || :' >mergetools-merge.txt && \
+		show_tool_names can_merge' | sed -e "s/\([a-z0-9]*\)/\`\1\`;;/" >mergetools-merge.txt && \
 	date >$@
 
 TRACK_ASCIIDOCFLAGS = $(subst ','\'',$(ASCIIDOC_COMMON):$(ASCIIDOC_HTML):$(ASCIIDOC_DOCBOOK))
diff mbox series

Patch

diff --git a/Documentation/config/mergetool.txt b/Documentation/config/mergetool.txt
index cafbbef46a..13f1b234db 100644
--- a/Documentation/config/mergetool.txt
+++ b/Documentation/config/mergetool.txt
@@ -45,6 +45,15 @@  mergetool.meld.useAutoMerge::
 	value of `false` avoids using `--auto-merge` altogether, and is the
 	default value.
 
+mergetool.vimdiff.layout::
+	The vimdiff backend uses this variable to control how its split
+	windows look like. Applies even if you are using Neovim (`nvim`) or
+	gVim (`gvim`) as the merge tool. See BACKEND SPECIFIC HINTS section
+ifndef::git-mergetool[]
+	(on linkgit:git-mergetool[1])
+endif::[]
+	for details.
+
 mergetool.hideResolved::
 	During a merge Git will automatically resolve as many conflicts as
 	possible and write the 'MERGED' file containing conflict markers around
diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt
index e587c7763a..f784027bc1 100644
--- a/Documentation/git-mergetool.txt
+++ b/Documentation/git-mergetool.txt
@@ -101,6 +101,7 @@  success of the resolution after the custom tool has exited.
 
 CONFIGURATION
 -------------
+:git-mergetool: 1
 include::config/mergetool.txt[]
 
 TEMPORARY FILES
@@ -113,6 +114,13 @@  Setting the `mergetool.keepBackup` configuration variable to `false`
 causes `git mergetool` to automatically remove the backup as files
 are successfully merged.
 
+BACKEND SPECIFIC HINTS
+----------------------
+
+vimdiff
+~~~~~~~
+include::mergetools/vimdiff.txt[]
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/mergetools/vimdiff.txt b/Documentation/mergetools/vimdiff.txt
new file mode 100644
index 0000000000..f63fc48c29
--- /dev/null
+++ b/Documentation/mergetools/vimdiff.txt
@@ -0,0 +1,189 @@ 
+Description
+^^^^^^^^^^^
+
+When specifying `--tool=vimdiff` in `git mergetool` Git will open Vim with a 4
+windows layout distributed in the following way:
+
+    ------------------------------------------
+    |             |           |              |
+    |   LOCAL     |   BASE    |   REMOTE     |
+    |             |           |              |
+    ------------------------------------------
+    |                                        |
+    |                MERGED                  |
+    |                                        |
+    ------------------------------------------
+
+`LOCAL`, `BASE` and `REMOTE` are read-only buffers showing the contents of the
+conflicting file in specific commits ("commit you are merging into", "common
+ancestor commit" and "commit you are merging from" respectively)
+
+`MERGED` is a writable buffer where you have to resolve the conflicts (using the
+other read-only buffers as a reference). Once you are done, save and exit Vim as
+usual (`:wq`) or, if you want to abort, exit using `:cq`.
+
+Layout configuration
+^^^^^^^^^^^^^^^^^^^^
+
+You can change the windows layout used by Vim by setting configuration variable
+`mergetool.vimdiff.layout` which accepts a string where the following separators
+have special meaning:
+
+  - `+` is used to "open a new tab"
+  - `,` is used to "open a new vertical split"
+  - `/` is used to "open a new horizontal split"
+  - `@` is used to indicate which is the file containing the final version after
+    solving the conflicts. If not present, `MERGED` will be used by default.
+
+The precedence of the operators is this one (you can use parentheses to change
+it):
+
+    `@` > `+` > `/` > `,`
+
+Let's see some examples to understand how it works:
+
+* `layout = "(LOCAL,BASE,REMOTE)/MERGED"`
++
+--
+This is exactly the same as the default layout we have already seen.
+
+Note that `/` has precedence over `,` and thus the parenthesis are not
+needed in this case. The next layout definition is equivalent:
+
+    layout = "LOCAL,BASE,REMOTE / MERGED"
+--
+* `layout = "LOCAL,MERGED,REMOTE"`
++
+--
+If, for some reason, we are not interested in the `BASE` buffer.
+
+           ------------------------------------------
+           |             |           |              |
+           |             |           |              |
+           |   LOCAL     |   MERGED  |   REMOTE     |
+           |             |           |              |
+           |             |           |              |
+           ------------------------------------------
+--
+* `layout = "MERGED"`
++
+--
+Only the `MERGED` buffer will be shown. Note, however, that all the other
+ones are still loaded in vim, and you can access them with the "buffers"
+command.
+
+           ------------------------------------------
+           |                                        |
+           |                                        |
+           |                 MERGED                 |
+           |                                        |
+           |                                        |
+           ------------------------------------------
+--
+* `layout = "@LOCAL,REMOTE"`
++
+--
+When `MERGED` is not present in the layout, you must "mark" one of the
+buffers with an asterisk. That will become the buffer you need to edit and
+save after resolving the conflicts.
+
+           ------------------------------------------
+           |                   |                    |
+           |                   |                    |
+           |                   |                    |
+           |     LOCAL         |    REMOTE          |
+           |                   |                    |
+           |                   |                    |
+           |                   |                    |
+           ------------------------------------------
+--
+* `layout = "LOCAL,BASE,REMOTE / MERGED + BASE,LOCAL + BASE,REMOTE"`
++
+--
+Three tabs will open: the first one is a copy of the default layout, while
+the other two only show the differences between (`BASE` and `LOCAL`) and
+(`BASE` and `REMOTE`) respectively.
+
+           ------------------------------------------
+           | <TAB #1> |  TAB #2  |  TAB #3  |       |
+           ------------------------------------------
+           |             |           |              |
+           |   LOCAL     |   BASE    |   REMOTE     |
+           |             |           |              |
+           ------------------------------------------
+           |                                        |
+           |                MERGED                  |
+           |                                        |
+           ------------------------------------------
+
+           ------------------------------------------
+           |  TAB #1  | <TAB #2> |  TAB #3  |       |
+           ------------------------------------------
+           |                   |                    |
+           |                   |                    |
+           |                   |                    |
+           |     BASE          |    LOCAL           |
+           |                   |                    |
+           |                   |                    |
+           |                   |                    |
+           ------------------------------------------
+
+           ------------------------------------------
+           |  TAB #1  |  TAB #2  | <TAB #3> |       |
+           ------------------------------------------
+           |                   |                    |
+           |                   |                    |
+           |                   |                    |
+           |     BASE          |    REMOTE          |
+           |                   |                    |
+           |                   |                    |
+           |                   |                    |
+           ------------------------------------------
+--
+* `layout = "LOCAL,BASE,REMOTE / MERGED + BASE,LOCAL + BASE,REMOTE + (LOCAL/BASE/REMOTE),MERGED"`
++
+--
+Same as the previous example, but adds a fourth tab with the same
+information as the first tab, with a different layout.
+
+           ---------------------------------------------
+           |  TAB #1  |  TAB #2  |  TAB #3  | <TAB #4> |
+           ---------------------------------------------
+           |       LOCAL         |                     |
+           |---------------------|                     |
+           |       BASE          |        MERGED       |
+           |---------------------|                     |
+           |       REMOTE        |                     |
+           ---------------------------------------------
+
+Note how in the third tab definition we need to use parenthesis to make `,`
+have precedence over `/`.
+--
+
+Variants
+^^^^^^^^
+
+Instead of `--tool=vimdiff`, you can also use one of these other variants:
+
+  * `--tool=gvimdiff`, to open gVim instead of Vim.
+
+  * `--tool=nvimdiff`, to open Neovim instead of Vim.
+
+When using these variants, in order to specify a custom layout you will have to
+set configuration variables `mergetool.gvimdiff.layout` and
+`mergetool.nvimdiff.layout` instead of `mergetool.vimdiff.layout`
+
+In addition, for backwards compatibility with previous Git versions, you can
+also append `1`, `2` or `3` to either `vimdiff` 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 variable
+`mergetool.[g,n,]vimdiff.layout` to...
+
+  * `x=1`: `"@LOCAL, REMOTE"`
+  * `x=2`: `"LOCAL, MERGED, REMOTE"`
+  * `x=3`: `"MERGED"`
+
+Example: using `--tool=gvimdiff2` will open `gvim` with three columns (LOCAL,
+MERGED and REMOTE).
+
diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
index 542a6a75eb..9f99201bcc 100644
--- a/git-mergetool--lib.sh
+++ b/git-mergetool--lib.sh
@@ -63,7 +63,7 @@  $(list_tool_variants)"
 					preamble=
 				fi
 				shown_any=yes
-				printf "%s%s\n" "$per_line_prefix" "$toolname"
+				printf "%s%-15s  %s\n" "$per_line_prefix" "$toolname" $(diff_mode && diff_cmd_help "$toolname" || merge_cmd_help "$toolname")
 			fi
 		done
 
@@ -162,10 +162,18 @@  setup_tool () {
 		return 1
 	}
 
+	diff_cmd_help () {
+		return 0
+	}
+
 	merge_cmd () {
 		return 1
 	}
 
+	merge_cmd_help () {
+		return 0
+	}
+
 	hide_resolved_enabled () {
 		return 0
 	}
diff --git a/mergetools/vimdiff b/mergetools/vimdiff
index 9d1bf4f455..461a89b6f9 100644
--- a/mergetools/vimdiff
+++ b/mergetools/vimdiff
@@ -365,6 +365,25 @@  diff_cmd () {
 }
 
 
+diff_cmd_help () {
+	TOOL=$1
+
+	case "$TOOL" in
+	nvimdiff*)
+		printf "Use Neovim"
+		;;
+	gvimdiff*)
+		printf "Use gVim (requires a graphical session)"
+		;;
+	vimdiff*)
+		printf "Use Vim"
+		;;
+	esac
+
+	return 0
+}
+
+
 merge_cmd () {
 	layout=$(git config mergetool.vimdiff.layout)
 
@@ -436,6 +455,40 @@  merge_cmd () {
 }
 
 
+merge_cmd_help () {
+	TOOL=$1
+
+	case "$TOOL" in
+	nvimdiff*)
+		printf "Use Neovim "
+		;;
+	gvimdiff*)
+		printf "Use gVim (requires a graphical session) "
+		;;
+	vimdiff*)
+		printf "Use Vim "
+		;;
+	esac
+
+	case "$TOOL" in
+	*1)
+		echo "with a 2 panes layout (LOCAL and REMOTE)"
+		;;
+	*2)
+		echo "with a 3 panes layout (LOCAL, MERGED and REMOTE)"
+		;;
+	*3)
+		echo "where only the MERGED file is shown"
+		;;
+	*)
+		echo "with a custom layout (see \`git help mergetool\`'s \`BACKEND SPECIFIC HINTS\` section)"
+		;;
+	esac
+
+	return 0
+}
+
+
 translate_merge_tool_path () {
 	case "$1" in
 	nvimdiff*)