diff options
authorCharles Bailey <>2008-02-21 23:31:12 (GMT)
committerJunio C Hamano <>2008-03-05 20:07:04 (GMT)
commit964473a0429f625d019c69ab55644540174acf85 (patch)
parentb3ea27e4de24c7006969f493ba6bfbbc5b572d80 (diff)
Teach git mergetool to use custom commands defined at config time
Currently git mergetool is restricted to a set of commands defined in the script. You can subvert the mergetool.<tool>.path to force git mergetool to use a different command, but if you have a command whose invocation syntax does not match one of the current tools then you would have to write a wrapper script for it. This patch adds two git config variable patterns which allow a more flexible choice of merge tool. If you run git mergetool with -t/--tool or the merge.tool config variable set to an unrecognized tool then git mergetool will query the mergetool.<tool>.cmd config variable. If this variable exists, then git mergetool will treat the specified tool as a custom command and will use a shell eval to run the command with the documented shell variables set. mergetool.<tool>.trustExitCode can be used to indicate that the exit code of the custom command can be used to determine the success of the merge. Signed-off-by: Charles Bailey <> Signed-off-by: Junio C Hamano <>
2 files changed, 49 insertions, 4 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 5141690..29bc516 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -749,8 +749,10 @@ merge.summary::
Controls which merge resolution program is used by
- linkgit:git-mergetool[1]. Valid values are: "kdiff3", "tkdiff",
- "meld", "xxdiff", "emerge", "vimdiff", "gvimdiff", and "opendiff".
+ linkgit:git-mergetool[1]. Valid built-in values are: "kdiff3",
+ "tkdiff", "meld", "xxdiff", "emerge", "vimdiff", "gvimdiff", and
+ "opendiff". Any other value is treated is custom merge tool
+ and there must be a corresponing mergetool.<tool>.cmd option.
Controls the amount of output shown by the recursive merge
@@ -777,6 +779,25 @@ mergetool.<tool>.path::
Override the path for the given tool. This is useful in case
your tool is not in the PATH.
+ Specify the command to invoke the specified merge tool. The
+ specified command is evaluated in shell with the following
+ variables available: 'BASE' is the name of a temporary file
+ containing the common base of the files to be merged, if available;
+ 'LOCAL' is the name of a temporary file containing the contents of
+ the file on the current branch; 'REMOTE' is the name of a temporary
+ file containing the contents of the file from the branch being
+ merged; 'MERGED' contains the name of the file to which the merge
+ tool should write the results of a successful merge.
+ For a custom merge command, specify whether the exit code of
+ the merge command can be used to determine whether the merge was
+ successful. If this is not set to true then the merge target file
+ timestamp is checked and the merge assumed to have been successful
+ if the file has been updated, otherwise the user is prompted to
+ indicate the success of the merge.
After performing a merge, the original file with conflict markers
can be saved as a file with a `.orig` extension. If this variable
diff --git a/ b/
index 2199c62..5c86f69 100755
--- a/
+++ b/
@@ -251,6 +251,18 @@ merge_file () {
+ *)
+ if test -n "$merge_tool_cmd"; then
+ if test "$merge_tool_trust_exit_code" = "false"; then
+ touch "$BACKUP"
+ ( eval $merge_tool_cmd )
+ check_unchanged
+ else
+ ( eval $merge_tool_cmd )
+ status=$?
+ fi
+ fi
+ ;;
if test "$status" -ne 0; then
echo "merge of $MERGED failed" 1>&2
@@ -296,12 +308,20 @@ do
+ merge_tool_cmd="$(git config mergetool.$1.cmd)"
+ test -n "$merge_tool_cmd"
valid_tool() {
case "$1" in
kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | ecmerge)
;; # happy
- return 1
+ if ! valid_custom_tool "$1"; then
+ return 1
+ fi
@@ -369,10 +389,14 @@ else
merge_keep_backup="$(git config --bool merge.keepBackup || echo true)"
- if ! type "$merge_tool_path" > /dev/null 2>&1; then
+ if test -z "$merge_tool_cmd" && ! type "$merge_tool_path" > /dev/null 2>&1; then
echo "The merge tool $merge_tool is not available as '$merge_tool_path'"
exit 1
+ if ! test -z "$merge_tool_cmd"; then
+ merge_tool_trust_exit_code="$(git config --bool mergetool.$merge_tool.trustExitCode || echo false)"
+ fi