aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2022-05-10 17:41:11 -0700
committerJunio C Hamano <gitster@pobox.com>2022-05-10 17:41:11 -0700
commit123dfdff0d6e886ce5536d39dd77dcd46db8d4c0 (patch)
treef4773e28ec45311814abcd32f94ab581a2a24895
parentMerge branch 'jh/p4-various-fixups' (diff)
parentmergetools: add description to all diff/merge tools (diff)
downloadgit-123dfdff0d6e886ce5536d39dd77dcd46db8d4c0.tar.gz
git-123dfdff0d6e886ce5536d39dd77dcd46db8d4c0.zip
Merge branch 'fr/vimdiff-layout'
Reimplement "vimdiff[123]" mergetool drivers with a more generic layout mechanism. * fr/vimdiff-layout: mergetools: add description to all diff/merge tools vimdiff: add tool documentation vimdiff: integrate layout tests in the unit tests framework ('t' folder) vimdiff: new implementation with layout support
-rw-r--r--Documentation/Makefile8
-rw-r--r--Documentation/config/mergetool.txt9
-rw-r--r--Documentation/git-mergetool.txt8
-rw-r--r--Documentation/mergetools/vimdiff.txt194
-rw-r--r--git-mergetool--lib.sh10
-rw-r--r--mergetools/araxis8
-rw-r--r--mergetools/bc8
-rw-r--r--mergetools/codecompare8
-rw-r--r--mergetools/deltawalker8
-rw-r--r--mergetools/diffmerge8
-rw-r--r--mergetools/diffuse8
-rw-r--r--mergetools/ecmerge8
-rw-r--r--mergetools/emerge8
-rw-r--r--mergetools/examdiff8
-rw-r--r--mergetools/guiffy8
-rw-r--r--mergetools/kdiff38
-rw-r--r--mergetools/kompare8
-rw-r--r--mergetools/meld8
-rw-r--r--mergetools/opendiff8
-rw-r--r--mergetools/p4merge8
-rw-r--r--mergetools/smerge8
-rw-r--r--mergetools/tkdiff8
-rw-r--r--mergetools/tortoisemerge8
-rw-r--r--mergetools/vimdiff607
-rw-r--r--mergetools/winmerge8
-rw-r--r--mergetools/xxdiff8
-rwxr-xr-xt/t7609-mergetool--lib.sh14
27 files changed, 978 insertions, 32 deletions
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 44c080e3e5..adb2f1b50a 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -302,12 +302,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 --git a/Documentation/config/mergetool.txt b/Documentation/config/mergetool.txt
index cafbbef46a..90b3809700 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[]
+ in 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..2d631e9b1f
--- /dev/null
+++ b/Documentation/mergetools/vimdiff.txt
@@ -0,0 +1,194 @@
+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/araxis b/mergetools/araxis
index e2407b65b7..eb32a7da95 100644
--- a/mergetools/araxis
+++ b/mergetools/araxis
@@ -2,6 +2,10 @@ diff_cmd () {
"$merge_tool_path" -wait -2 "$LOCAL" "$REMOTE" >/dev/null 2>&1
}
+diff_cmd_help () {
+ echo "Use Araxis Merge (requires a graphical session)"
+}
+
merge_cmd () {
if $base_present
then
@@ -13,6 +17,10 @@ merge_cmd () {
fi
}
+merge_cmd_help () {
+ echo "Use Araxis Merge (requires a graphical session)"
+}
+
translate_merge_tool_path() {
echo compare
}
diff --git a/mergetools/bc b/mergetools/bc
index 26c19d46a5..2922667ddd 100644
--- a/mergetools/bc
+++ b/mergetools/bc
@@ -2,6 +2,10 @@ diff_cmd () {
"$merge_tool_path" "$LOCAL" "$REMOTE"
}
+diff_cmd_help () {
+ echo "Use Beyond Compare (requires a graphical session)"
+}
+
merge_cmd () {
if $base_present
then
@@ -13,6 +17,10 @@ merge_cmd () {
fi
}
+merge_cmd_help () {
+ echo "Use Beyond Compare (requires a graphical session)"
+}
+
translate_merge_tool_path() {
if type bcomp >/dev/null 2>/dev/null
then
diff --git a/mergetools/codecompare b/mergetools/codecompare
index 9f60e8da65..610963d377 100644
--- a/mergetools/codecompare
+++ b/mergetools/codecompare
@@ -2,6 +2,10 @@ diff_cmd () {
"$merge_tool_path" "$LOCAL" "$REMOTE"
}
+diff_cmd_help () {
+ echo "Use Code Compare (requires a graphical session)"
+}
+
merge_cmd () {
if $base_present
then
@@ -13,6 +17,10 @@ merge_cmd () {
fi
}
+merge_cmd_help () {
+ echo "Use Code Compare (requires a graphical session)"
+}
+
translate_merge_tool_path() {
if merge_mode
then
diff --git a/mergetools/deltawalker b/mergetools/deltawalker
index ee6f374bce..efae4c285c 100644
--- a/mergetools/deltawalker
+++ b/mergetools/deltawalker
@@ -2,6 +2,10 @@ diff_cmd () {
"$merge_tool_path" "$LOCAL" "$REMOTE" >/dev/null 2>&1
}
+diff_cmd_help () {
+ echo "Use DeltaWalker (requires a graphical session)"
+}
+
merge_cmd () {
# Adding $(pwd)/ in front of $MERGED should not be necessary.
# However without it, DeltaWalker (at least v1.9.8 on Windows)
@@ -16,6 +20,10 @@ merge_cmd () {
fi >/dev/null 2>&1
}
+merge_cmd_help () {
+ echo "Use DeltaWalker (requires a graphical session)"
+}
+
translate_merge_tool_path () {
echo DeltaWalker
}
diff --git a/mergetools/diffmerge b/mergetools/diffmerge
index 9b6355b98a..9b5b62d1ca 100644
--- a/mergetools/diffmerge
+++ b/mergetools/diffmerge
@@ -2,6 +2,10 @@ diff_cmd () {
"$merge_tool_path" "$LOCAL" "$REMOTE" >/dev/null 2>&1
}
+diff_cmd_help () {
+ echo "Use DiffMerge (requires a graphical session)"
+}
+
merge_cmd () {
if $base_present
then
@@ -13,6 +17,10 @@ merge_cmd () {
fi
}
+merge_cmd_help () {
+ echo "Use DiffMerge (requires a graphical session)"
+}
+
exit_code_trustable () {
true
}
diff --git a/mergetools/diffuse b/mergetools/diffuse
index 5a3ae8b569..ebfaba5172 100644
--- a/mergetools/diffuse
+++ b/mergetools/diffuse
@@ -2,6 +2,10 @@ diff_cmd () {
"$merge_tool_path" "$LOCAL" "$REMOTE" | cat
}
+diff_cmd_help () {
+ echo "Use Diffuse (requires a graphical session)"
+}
+
merge_cmd () {
if $base_present
then
@@ -13,3 +17,7 @@ merge_cmd () {
"$LOCAL" "$MERGED" "$REMOTE" | cat
fi
}
+
+merge_cmd_help () {
+ echo "Use Diffuse (requires a graphical session)"
+}
diff --git a/mergetools/ecmerge b/mergetools/ecmerge
index 6c5101c4f7..0d4d609874 100644
--- a/mergetools/ecmerge
+++ b/mergetools/ecmerge
@@ -2,6 +2,10 @@ diff_cmd () {
"$merge_tool_path" --default --mode=diff2 "$LOCAL" "$REMOTE"
}
+diff_cmd_help () {
+ echo "Use ECMerge (requires a graphical session)"
+}
+
merge_cmd () {
if $base_present
then
@@ -12,3 +16,7 @@ merge_cmd () {
--default --mode=merge2 --to="$MERGED"
fi
}
+
+merge_cmd_help () {
+ echo "Use ECMerge (requires a graphical session)"
+}
diff --git a/mergetools/emerge b/mergetools/emerge
index d1ce513ff5..fc6892cc95 100644
--- a/mergetools/emerge
+++ b/mergetools/emerge
@@ -2,6 +2,10 @@ diff_cmd () {
"$merge_tool_path" -f emerge-files-command "$LOCAL" "$REMOTE"
}
+diff_cmd_help () {
+ echo "Use Emacs' Emerge"
+}
+
merge_cmd () {
if $base_present
then
@@ -17,6 +21,10 @@ merge_cmd () {
fi
}
+merge_cmd_help () {
+ echo "Use Emacs' Emerge"
+}
+
translate_merge_tool_path() {
echo emacs
}
diff --git a/mergetools/examdiff b/mergetools/examdiff
index e72b06fc4d..6f53ca9161 100644
--- a/mergetools/examdiff
+++ b/mergetools/examdiff
@@ -2,6 +2,10 @@ diff_cmd () {
"$merge_tool_path" "$LOCAL" "$REMOTE" -nh
}
+diff_cmd_help () {
+ echo "Use ExamDiff Pro (requires a graphical session)"
+}
+
merge_cmd () {
if $base_present
then
@@ -11,6 +15,10 @@ merge_cmd () {
fi
}
+merge_cmd_help () {
+ echo "Use ExamDiff Pro (requires a graphical session)"
+}
+
translate_merge_tool_path() {
mergetool_find_win32_cmd "ExamDiff.com" "ExamDiff Pro"
}
diff --git a/mergetools/guiffy b/mergetools/guiffy
index 8b23a13c41..3ed07efd16 100644
--- a/mergetools/guiffy
+++ b/mergetools/guiffy
@@ -2,6 +2,10 @@ diff_cmd () {
"$merge_tool_path" "$LOCAL" "$REMOTE"
}
+diff_cmd_help () {
+ echo "Use Guiffy's Diff Tool (requires a graphical session)"
+}
+
merge_cmd () {
if $base_present
then
@@ -13,6 +17,10 @@ merge_cmd () {
fi
}
+merge_cmd_help () {
+ echo "Use Guiffy's Diff Tool (requires a graphical session)"
+}
+
exit_code_trustable () {
true
}
diff --git a/mergetools/kdiff3 b/mergetools/kdiff3
index 520cb914a1..ee8b3a0570 100644
--- a/mergetools/kdiff3
+++ b/mergetools/kdiff3
@@ -4,6 +4,10 @@ diff_cmd () {
"$LOCAL" "$REMOTE" >/dev/null 2>&1
}
+diff_cmd_help () {
+ echo "Use KDiff3 (requires a graphical session)"
+}
+
merge_cmd () {
if $base_present
then
@@ -22,6 +26,10 @@ merge_cmd () {
fi
}
+merge_cmd_help () {
+ echo "Use KDiff3 (requires a graphical session)"
+}
+
exit_code_trustable () {
true
}
diff --git a/mergetools/kompare b/mergetools/kompare
index e8c0bfa678..4ce23dbe8b 100644
--- a/mergetools/kompare
+++ b/mergetools/kompare
@@ -2,10 +2,18 @@ can_merge () {
return 1
}
+diff_cmd_help () {
+ echo "Use Kompare (requires a graphical session)"
+}
+
diff_cmd () {
"$merge_tool_path" "$LOCAL" "$REMOTE"
}
+merge_cmd_help () {
+ echo "Use Kompare (requires a graphical session)"
+}
+
exit_code_trustable () {
true
}
diff --git a/mergetools/meld b/mergetools/meld
index aab4ebb935..8ec0867e03 100644
--- a/mergetools/meld
+++ b/mergetools/meld
@@ -2,6 +2,10 @@ diff_cmd () {
"$merge_tool_path" "$LOCAL" "$REMOTE"
}
+diff_cmd_help () {
+ echo "Use Meld (requires a graphical session)"
+}
+
merge_cmd () {
check_meld_for_features
@@ -20,6 +24,10 @@ merge_cmd () {
fi
}
+merge_cmd_help () {
+ echo "Use Meld (requires a graphical session) with optional \`auto merge\` (see \`git help mergetool\`'s \`CONFIGURATION\` section)"
+}
+
# Get meld help message
init_meld_help_msg () {
if test -z "$meld_help_msg"
diff --git a/mergetools/opendiff b/mergetools/opendiff
index b608dd6de3..44adf8f951 100644
--- a/mergetools/opendiff
+++ b/mergetools/opendiff
@@ -2,6 +2,10 @@ diff_cmd () {
"$merge_tool_path" "$LOCAL" "$REMOTE" | cat
}
+diff_cmd_help () {
+ echo "Use FileMerge (requires a graphical session)"
+}
+
merge_cmd () {
if $base_present
then
@@ -12,3 +16,7 @@ merge_cmd () {
-merge "$MERGED" | cat
fi
}
+
+merge_cmd_help () {
+ echo "Use FileMerge (requires a graphical session)"
+}
diff --git a/mergetools/p4merge b/mergetools/p4merge
index 7a5b291dd2..f3cb197e58 100644
--- a/mergetools/p4merge
+++ b/mergetools/p4merge
@@ -19,6 +19,10 @@ diff_cmd () {
fi
}
+diff_cmd_help () {
+ echo "Use HelixCore P4Merge (requires a graphical session)"
+}
+
merge_cmd () {
if ! $base_present
then
@@ -34,3 +38,7 @@ create_empty_file () {
printf "%s" "$empty_file"
}
+
+merge_cmd_help () {
+ echo "Use HelixCore P4Merge (requires a graphical session)"
+}
diff --git a/mergetools/smerge b/mergetools/smerge
index 9c2e6f6fd7..5410835a6b 100644
--- a/mergetools/smerge
+++ b/mergetools/smerge
@@ -2,6 +2,10 @@ diff_cmd () {
"$merge_tool_path" mergetool "$LOCAL" "$REMOTE" -o "$MERGED"
}
+diff_cmd_help () {
+ echo "Use Sublime Merge (requires a graphical session)"
+}
+
merge_cmd () {
if $base_present
then
@@ -10,3 +14,7 @@ merge_cmd () {
"$merge_tool_path" mergetool "$LOCAL" "$REMOTE" -o "$MERGED"
fi
}
+
+merge_cmd_help () {
+ echo "Use Sublime Merge (requires a graphical session)"
+}
diff --git a/mergetools/tkdiff b/mergetools/tkdiff
index eee5cb57e3..66906a720d 100644
--- a/mergetools/tkdiff
+++ b/mergetools/tkdiff
@@ -2,6 +2,10 @@ diff_cmd () {
"$merge_tool_path" "$LOCAL" "$REMOTE"
}
+diff_cmd_help () {
+ echo "Use TkDiff (requires a graphical session)"
+}
+
merge_cmd () {
if $base_present
then
@@ -14,3 +18,7 @@ merge_cmd () {
exit_code_trustable () {
true
}
+
+merge_cmd_help () {
+ echo "Use TkDiff (requires a graphical session)"
+}
diff --git a/mergetools/tortoisemerge b/mergetools/tortoisemerge
index d7ab666a59..507edcd444 100644
--- a/mergetools/tortoisemerge
+++ b/mergetools/tortoisemerge
@@ -2,6 +2,10 @@ can_diff () {
return 1
}
+diff_cmd_help () {
+ echo "Use TortoiseMerge (requires a graphical session)"
+}
+
merge_cmd () {
if $base_present
then
@@ -30,3 +34,7 @@ translate_merge_tool_path() {
echo tortoisemerge
fi
}
+
+merge_cmd_help () {
+ echo "Use TortoiseMerge (requires a graphical session)"
+}
diff --git a/mergetools/vimdiff b/mergetools/vimdiff
index 96f6209a04..461a89b6f9 100644
--- a/mergetools/vimdiff
+++ b/mergetools/vimdiff
@@ -1,49 +1,495 @@
+# This script can be run in two different contexts:
+#
+# - From git, when the user invokes the "vimdiff" merge tool. In this context
+# this script expects the following environment variables (among others) to
+# be defined (which is something "git" takes care of):
+#
+# - $BASE
+# - $LOCAL
+# - $REMOTE
+# - $MERGED
+#
+# In this mode, all this script does is to run the next command:
+#
+# vim -f -c ... $LOCAL $BASE $REMOTE $MERGED
+#
+# ...where the "..." string depends on the value of the
+# "mergetool.vimdiff.layout" configuration variable and is used to open vim
+# with a certain layout of buffers, windows and tabs.
+#
+# - From a script inside the unit tests framework folder ("t" folder) by
+# sourcing this script and then manually calling "run_unit_tests", which
+# will run a battery of unit tests to make sure nothing breaks.
+# In this context this script does not expect any particular environment
+# variable to be set.
+
+
+################################################################################
+## Internal functions (not meant to be used outside this script)
+################################################################################
+
+debug_print () {
+ # Send message to stderr if global variable GIT_MERGETOOL_VIMDIFF is set
+ # to "true"
+
+ if test -n "$GIT_MERGETOOL_VIMDIFF_DEBUG"
+ then
+ >&2 echo "$@"
+ fi
+}
+
+substring () {
+ # Return a substring of $1 containing $3 characters starting at
+ # zero-based offset $2.
+ #
+ # Examples:
+ #
+ # substring "Hello world" 0 4 --> "Hell"
+ # substring "Hello world" 3 4 --> "lo w"
+ # substring "Hello world" 3 10 --> "lo world"
+
+ STRING=$1
+ START=$2
+ LEN=$3
+
+ echo "$STRING" | cut -c$(( START + 1 ))-$(( START + $LEN ))
+}
+
+gen_cmd_aux () {
+ # Auxiliary function used from "gen_cmd()".
+ # Read that other function documentation for more details.
+
+ LAYOUT=$1
+ CMD=$2 # This is a second (hidden) argument used for recursion
+
+ debug_print
+ debug_print "LAYOUT : $LAYOUT"
+ debug_print "CMD : $CMD"
+
+ if test -z "$CMD"
+ then
+ CMD="echo" # vim "nop" operator
+ fi
+
+ start=0
+ end=${#LAYOUT}
+
+ nested=0
+ nested_min=100
+
+
+ # Step 1:
+ #
+ # Increase/decrease "start"/"end" indices respectively to get rid of
+ # outer parenthesis.
+ #
+ # Example:
+ #
+ # - BEFORE: (( LOCAL , BASE ) / MERGED )
+ # - AFTER : ( LOCAL , BASE ) / MERGED
+
+ oldIFS=$IFS
+ IFS=#
+ for c in $(echo "$LAYOUT" | sed 's:.:&#:g')
+ do
+ if test "$c" = " "
+ then
+ continue
+ fi
+
+ if test "$c" = "("
+ then
+ nested=$(( nested + 1 ))
+ continue
+ fi
+
+ if test "$c" = ")"
+ then
+ nested=$(( nested - 1 ))
+ continue
+ fi
+
+ if test "$nested" -lt "$nested_min"
+ then
+ nested_min=$nested
+ fi
+ done
+ IFS=$oldIFS
+
+ debug_print "NESTED MIN: $nested_min"
+
+ while test "$nested_min" -gt "0"
+ do
+ start=$(( start + 1 ))
+ end=$(( end - 1 ))
+
+ start_minus_one=$(( start - 1 ))
+
+ while ! test "$(substring "$LAYOUT" "$start_minus_one" 1)" = "("
+ do
+ start=$(( start + 1 ))
+ start_minus_one=$(( start_minus_one + 1 ))
+ done
+
+ while ! test "$(substring "$LAYOUT" "$end" 1)" = ")"
+ do
+ end=$(( end - 1 ))
+ done
+
+ nested_min=$(( nested_min - 1 ))
+ done
+
+ debug_print "CLEAN : $(substring "$LAYOUT" "$start" "$(( end - start ))")"
+
+
+ # Step 2:
+ #
+ # Search for all valid separators ("+", "/" or ",") which are *not*
+ # inside parenthesis. Save the index at which each of them makes the
+ # first appearance.
+
+ index_new_tab=""
+ index_horizontal_split=""
+ index_vertical_split=""
+
+ nested=0
+ i=$(( start - 1 ))
+
+ oldIFS=$IFS
+ IFS=#
+ for c in $(substring "$LAYOUT" "$start" "$(( end - start ))" | sed 's:.:&#:g');
+ do
+ i=$(( i + 1 ))
+
+ if test "$c" = " "
+ then
+ continue
+ fi
+
+ if test "$c" = "("
+ then
+ nested=$(( nested + 1 ))
+ continue
+ fi
+
+ if test "$c" = ")"
+ then
+ nested=$(( nested - 1 ))
+ continue
+ fi
+
+ if test "$nested" = 0
+ then
+ current=$c
+
+ if test "$current" = "+"
+ then
+ if test -z "$index_new_tab"
+ then
+ index_new_tab=$i
+ fi
+
+ elif test "$current" = "/"
+ then
+ if test -z "$index_horizontal_split"
+ then
+ index_horizontal_split=$i
+ fi
+
+ elif test "$current" = ","
+ then
+ if test -z "$index_vertical_split"
+ then
+ index_vertical_split=$i
+ fi
+ fi
+ fi
+ done
+ IFS=$oldIFS
+
+
+ # Step 3:
+ #
+ # Process the separator with the highest order of precedence
+ # (";" has the highest precedence and "|" the lowest one).
+ #
+ # By "process" I mean recursively call this function twice: the first
+ # one with the substring at the left of the separator and the second one
+ # with the one at its right.
+
+ terminate="false"
+
+ if ! test -z "$index_new_tab"
+ then
+ before="-tabnew"
+ after="tabnext"
+ index=$index_new_tab
+ terminate="true"
+
+ elif ! test -z "$index_horizontal_split"
+ then
+ before="split"
+ after="wincmd j"
+ index=$index_horizontal_split
+ terminate="true"
+
+ elif ! test -z "$index_vertical_split"
+ then
+ before="vertical split"
+ after="wincmd l"
+ index=$index_vertical_split
+ terminate="true"
+ fi
+
+ if test "$terminate" = "true"
+ then
+ CMD="$CMD | $before"
+ CMD=$(gen_cmd_aux "$(substring "$LAYOUT" "$start" "$(( index - start ))")" "$CMD")
+ CMD="$CMD | $after"
+ CMD=$(gen_cmd_aux "$(substring "$LAYOUT" "$(( index + 1 ))" "$(( ${#LAYOUT} - index ))")" "$CMD")
+ echo "$CMD"
+ return
+ fi
+
+
+ # Step 4:
+ #
+ # If we reach this point, it means there are no separators and we just
+ # need to print the command to display the specified buffer
+
+ target=$(substring "$LAYOUT" "$start" "$(( end - start ))" | sed 's:[ @();|-]::g')
+
+ if test "$target" = "LOCAL"
+ then
+ CMD="$CMD | 1b"
+
+ elif test "$target" = "BASE"
+ then
+ CMD="$CMD | 2b"
+
+ elif test "$target" = "REMOTE"
+ then
+ CMD="$CMD | 3b"
+
+ elif test "$target" = "MERGED"
+ then
+ CMD="$CMD | 4b"
+
+ else
+ CMD="$CMD | ERROR: >$target<"
+ fi
+
+ echo "$CMD"
+ return
+}
+
+
+gen_cmd () {
+ # This function returns (in global variable FINAL_CMD) the string that
+ # you can use when invoking "vim" (as shown next) to obtain a given
+ # layout:
+ #
+ # $ vim -f $FINAL_CMD "$LOCAL" "$BASE" "$REMOTE" "$MERGED"
+ #
+ # It takes one single argument: a string containing the desired layout
+ # definition.
+ #
+ # The syntax of the "layout definitions" is explained in "Documentation/
+ # mergetools/vimdiff.txt" but you can already intuitively understand how
+ # it works by knowing that...
+ #
+ # * "+" means "a new vim tab"
+ # * "/" means "a new vim horizontal split"
+ # * "," means "a new vim vertical split"
+ #
+ # It also returns (in global variable FINAL_TARGET) the name ("LOCAL",
+ # "BASE", "REMOTE" or "MERGED") of the file that is marked with an "@",
+ # or "MERGED" if none of them is.
+ #
+ # Example:
+ #
+ # gen_cmd "@LOCAL , REMOTE"
+ # |
+ # `-> FINAL_CMD == "-c \"echo | vertical split | 1b | wincmd l | 3b | tabdo windo diffthis\" -c \"tabfirst\""
+ # FINAL_TARGET == "LOCAL"
+
+ LAYOUT=$1
+
+
+ # Search for a "@" in one of the files identifiers ("LOCAL", "BASE",
+ # "REMOTE", "MERGED"). If not found, use "MERGE" as the default file
+ # where changes will be saved.
+
+ if echo "$LAYOUT" | grep @LOCAL >/dev/null
+ then
+ FINAL_TARGET="LOCAL"
+ elif echo "$LAYOUT" | grep @BASE >/dev/null
+ then
+ FINAL_TARGET="BASE"
+ else
+ FINAL_TARGET="MERGED"
+ fi
+
+
+ # Obtain the first part of vim "-c" option to obtain the desired layout
+
+ CMD=$(gen_cmd_aux "$LAYOUT")
+
+
+ # Adjust the just obtained script depending on whether more than one
+ # windows are visible or not
+
+ if echo "$LAYOUT" | grep ",\|/" >/dev/null
+ then
+ CMD="$CMD | tabdo windo diffthis"
+ else
+ CMD="$CMD | bufdo diffthis"
+ fi
+
+
+ # Add an extra "-c" option to move to the first tab (notice that we
+ # can't simply append the command to the previous "-c" string as
+ # explained here: https://github.com/vim/vim/issues/9076
+
+ FINAL_CMD="-c \"$CMD\" -c \"tabfirst\""
+}
+
+
+################################################################################
+## API functions (called from "git-mergetool--lib.sh")
+################################################################################
+
diff_cmd () {
"$merge_tool_path" -R -f -d \
-c 'wincmd l' -c 'cd $GIT_PREFIX' "$LOCAL" "$REMOTE"
}
+
+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)
+
case "$1" in
*vimdiff)
- if $base_present
+ if test -z "$layout"
then
- "$merge_tool_path" -f -d -c '4wincmd w | wincmd J' \
- "$LOCAL" "$BASE" "$REMOTE" "$MERGED"
- else
- "$merge_tool_path" -f -d -c 'wincmd l' \
- "$LOCAL" "$MERGED" "$REMOTE"
+ # Default layout when none is specified
+ layout="(LOCAL,BASE,REMOTE)/MERGED"
fi
;;
*vimdiff1)
- "$merge_tool_path" -f -d \
- -c 'echon "Resolve conflicts leftward then save. Use :cq to abort."' \
- "$LOCAL" "$REMOTE"
- ret="$?"
- if test "$ret" -eq 0
- then
- cp -- "$LOCAL" "$MERGED"
- fi
- return "$ret"
+ layout="@LOCAL,REMOTE"
;;
*vimdiff2)
- "$merge_tool_path" -f -d -c 'wincmd l' \
- "$LOCAL" "$MERGED" "$REMOTE"
+ layout="LOCAL,MERGED,REMOTE"
;;
*vimdiff3)
- if $base_present
+ layout="MERGED"
+ ;;
+ esac
+
+ gen_cmd "$layout"
+
+ debug_print ""
+ debug_print "FINAL CMD : $FINAL_CMD"
+ debug_print "FINAL TAR : $FINAL_TARGET"
+
+ if $base_present
+ then
+ eval "$merge_tool_path" \
+ -f "$FINAL_CMD" "$LOCAL" "$BASE" "$REMOTE" "$MERGED"
+ else
+ # If there is no BASE (example: a merge conflict in a new file
+ # with the same name created in both braches which didn't exist
+ # before), close all BASE windows using vim's "quit" command
+
+ FINAL_CMD=$(echo "$FINAL_CMD" | \
+ sed -e 's:2b:quit:g' -e 's:3b:2b:g' -e 's:4b:3b:g')
+
+ eval "$merge_tool_path" \
+ -f "$FINAL_CMD" "$LOCAL" "$REMOTE" "$MERGED"
+ fi
+
+ ret="$?"
+
+ if test "$ret" -eq 0
+ then
+ case "$FINAL_TARGET" in
+ LOCAL)
+ source_path="$LOCAL"
+ ;;
+ REMOTE)
+ source_path="$REMOTE"
+ ;;
+ MERGED|*)
+ # Do nothing
+ source_path=
+ ;;
+ esac
+
+ if test -n "$source_path"
then
- "$merge_tool_path" -f -d -c 'hid | hid | hid' \
- "$LOCAL" "$REMOTE" "$BASE" "$MERGED"
- else
- "$merge_tool_path" -f -d -c 'hid | hid' \
- "$LOCAL" "$REMOTE" "$MERGED"
+ cp "$source_path" "$MERGED"
fi
+ fi
+
+ return "$ret"
+}
+
+
+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() {
+
+translate_merge_tool_path () {
case "$1" in
nvimdiff*)
echo nvim
@@ -57,14 +503,121 @@ translate_merge_tool_path() {
esac
}
+
exit_code_trustable () {
true
}
+
list_tool_variants () {
- for prefix in '' g n; do
- for suffix in '' 1 2 3; do
- echo "${prefix}vimdiff${suffix}"
+ if test "$TOOL_MODE" = "diff"
+ then
+ for prefix in '' g n
+ do
+ echo "${prefix}vimdiff"
+ done
+ else
+ for prefix in '' g n
+ do
+ for suffix in '' 1 2 3
+ do
+ echo "${prefix}vimdiff${suffix}"
+ done
done
+ fi
+}
+
+
+################################################################################
+## Unit tests (called from scripts inside the "t" folder)
+################################################################################
+
+run_unit_tests () {
+ # Function to make sure that we don't break anything when modifying this
+ # script.
+
+ NUMBER_OF_TEST_CASES=16
+
+ TEST_CASE_01="(LOCAL,BASE,REMOTE)/MERGED" # default behaviour
+ TEST_CASE_02="@LOCAL,REMOTE" # when using vimdiff1
+ TEST_CASE_03="LOCAL,MERGED,REMOTE" # when using vimdiff2
+ TEST_CASE_04="MERGED" # when using vimdiff3
+ TEST_CASE_05="LOCAL/MERGED/REMOTE"
+ TEST_CASE_06="(LOCAL/REMOTE),MERGED"
+ TEST_CASE_07="MERGED,(LOCAL/REMOTE)"
+ TEST_CASE_08="(LOCAL,REMOTE)/MERGED"
+ TEST_CASE_09="MERGED/(LOCAL,REMOTE)"
+ TEST_CASE_10="(LOCAL/BASE/REMOTE),MERGED"
+ TEST_CASE_11="(LOCAL,BASE,REMOTE)/MERGED+BASE,LOCAL+BASE,REMOTE+(LOCAL/BASE/REMOTE),MERGED"
+ TEST_CASE_12="((LOCAL,REMOTE)/BASE),MERGED"
+ TEST_CASE_13="((LOCAL,REMOTE)/BASE),((LOCAL/REMOTE),MERGED)"
+ TEST_CASE_14="BASE,REMOTE+BASE,LOCAL"
+ TEST_CASE_15=" (( (LOCAL , BASE , REMOTE) / MERGED)) +(BASE) , LOCAL+ BASE , REMOTE+ (((LOCAL / BASE / REMOTE)) , MERGED ) "
+ TEST_CASE_16="LOCAL,BASE,REMOTE / MERGED + BASE,LOCAL + BASE,REMOTE + (LOCAL / BASE / REMOTE),MERGED"
+
+ EXPECTED_CMD_01="-c \"echo | split | vertical split | 1b | wincmd l | vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_02="-c \"echo | vertical split | 1b | wincmd l | 3b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_03="-c \"echo | vertical split | 1b | wincmd l | vertical split | 4b | wincmd l | 3b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_04="-c \"echo | 4b | bufdo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_05="-c \"echo | split | 1b | wincmd j | split | 4b | wincmd j | 3b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_06="-c \"echo | vertical split | split | 1b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_07="-c \"echo | vertical split | 4b | wincmd l | split | 1b | wincmd j | 3b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_08="-c \"echo | split | vertical split | 1b | wincmd l | 3b | wincmd j | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_09="-c \"echo | split | 4b | wincmd j | vertical split | 1b | wincmd l | 3b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_10="-c \"echo | vertical split | split | 1b | wincmd j | split | 2b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_11="-c \"echo | -tabnew | split | vertical split | 1b | wincmd l | vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabnext | -tabnew | vertical split | 2b | wincmd l | 1b | tabnext | -tabnew | vertical split | 2b | wincmd l | 3b | tabnext | vertical split | split | 1b | wincmd j | split | 2b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_12="-c \"echo | vertical split | split | vertical split | 1b | wincmd l | 3b | wincmd j | 2b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_13="-c \"echo | vertical split | split | vertical split | 1b | wincmd l | 3b | wincmd j | 2b | wincmd l | vertical split | split | 1b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_14="-c \"echo | -tabnew | vertical split | 2b | wincmd l | 3b | tabnext | vertical split | 2b | wincmd l | 1b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_15="-c \"echo | -tabnew | split | vertical split | 1b | wincmd l | vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabnext | -tabnew | vertical split | 2b | wincmd l | 1b | tabnext | -tabnew | vertical split | 2b | wincmd l | 3b | tabnext | vertical split | split | 1b | wincmd j | split | 2b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_16="-c \"echo | -tabnew | split | vertical split | 1b | wincmd l | vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabnext | -tabnew | vertical split | 2b | wincmd l | 1b | tabnext | -tabnew | vertical split | 2b | wincmd l | 3b | tabnext | vertical split | split | 1b | wincmd j | split | 2b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+
+ EXPECTED_TARGET_01="MERGED"
+ EXPECTED_TARGET_02="LOCAL"
+ EXPECTED_TARGET_03="MERGED"
+ EXPECTED_TARGET_04="MERGED"
+ EXPECTED_TARGET_05="MERGED"
+ EXPECTED_TARGET_06="MERGED"
+ EXPECTED_TARGET_07="MERGED"
+ EXPECTED_TARGET_08="MERGED"
+ EXPECTED_TARGET_09="MERGED"
+ EXPECTED_TARGET_10="MERGED"
+ EXPECTED_TARGET_11="MERGED"
+ EXPECTED_TARGET_12="MERGED"
+ EXPECTED_TARGET_13="MERGED"
+ EXPECTED_TARGET_14="MERGED"
+ EXPECTED_TARGET_15="MERGED"
+ EXPECTED_TARGET_16="MERGED"
+
+ at_least_one_ko="false"
+
+ for i in $(seq -w 1 99)
+ do
+ if test "$i" -gt $NUMBER_OF_TEST_CASES
+ then
+ break
+ fi
+
+ gen_cmd "$(eval echo \${TEST_CASE_"$i"})"
+
+ if test "$FINAL_CMD" = "$(eval echo \${EXPECTED_CMD_"$i"})" \
+ && test "$FINAL_TARGET" = "$(eval echo \${EXPECTED_TARGET_"$i"})"
+ then
+ printf "Test Case #%02d: OK\n" "$(echo "$i" | sed 's/^0*//')"
+ else
+ printf "Test Case #%02d: KO !!!!\n" "$(echo "$i" | sed 's/^0*//')"
+ echo " FINAL_CMD : $FINAL_CMD"
+ echo " FINAL_CMD (expected) : $(eval echo \${EXPECTED_CMD_"$i"})"
+ echo " FINAL_TARGET : $FINAL_TARGET"
+ echo " FINAL_TARGET (expected): $(eval echo \${EXPECTED_TARGET_"$i"})"
+ at_least_one_ko="true"
+ fi
done
+
+ if test "$at_least_one_ko" = "true"
+ then
+ return 255
+ else
+ return 0
+ fi
}
diff --git a/mergetools/winmerge b/mergetools/winmerge
index 74d03259fd..36c72dde6e 100644
--- a/mergetools/winmerge
+++ b/mergetools/winmerge
@@ -3,6 +3,10 @@ diff_cmd () {
return 0
}
+diff_cmd_help () {
+ echo "Use WinMerge (requires a graphical session)"
+}
+
merge_cmd () {
# mergetool.winmerge.trustExitCode is implicitly false.
# touch $BACKUP so that we can check_unchanged.
@@ -13,3 +17,7 @@ merge_cmd () {
translate_merge_tool_path() {
mergetool_find_win32_cmd "WinMergeU.exe" "WinMerge"
}
+
+merge_cmd_help () {
+ echo "Use WinMerge (requires a graphical session)"
+}
diff --git a/mergetools/xxdiff b/mergetools/xxdiff
index d5ce467995..cd205f9842 100644
--- a/mergetools/xxdiff
+++ b/mergetools/xxdiff
@@ -12,6 +12,10 @@ diff_cmd () {
fi
}
+diff_cmd_help () {
+ echo "Use xxdiff (requires a graphical session)"
+}
+
merge_cmd () {
if $base_present
then
@@ -28,3 +32,7 @@ merge_cmd () {
--merged-file "$MERGED" "$LOCAL" "$REMOTE"
fi
}
+
+merge_cmd_help () {
+ echo "Use xxdiff (requires a graphical session)"
+}
diff --git a/t/t7609-mergetool--lib.sh b/t/t7609-mergetool--lib.sh
new file mode 100755
index 0000000000..d848fe6442
--- /dev/null
+++ b/t/t7609-mergetool--lib.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+test_description='git mergetool
+
+Testing basic merge tools options'
+
+. ./test-lib.sh
+
+test_expect_success 'mergetool --tool=vimdiff creates the expected layout' '
+ . $GIT_BUILD_DIR/mergetools/vimdiff &&
+ run_unit_tests
+'
+
+test_done