summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 240dc3e)
raw | patch | inline | side by side (parent: 240dc3e)
author | David Aguilar <davvid@gmail.com> | |
Thu, 18 Aug 2011 07:23:46 +0000 (00:23 -0700) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Fri, 19 Aug 2011 07:09:19 +0000 (00:09 -0700) |
Individual merge tools are now defined in a mergetools/$tool
file which is sourced at runtime.
The individual files are installed into $(git --exec-path)/mergetools/.
New tools can be added by creating a new file instead of editing the
git-mergetool--lib.sh scriptlet.
http://thread.gmane.org/gmane.comp.version-control.git/134906/focus=135006
Signed-off-by: David Aguilar <davvid@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
file which is sourced at runtime.
The individual files are installed into $(git --exec-path)/mergetools/.
New tools can be added by creating a new file instead of editing the
git-mergetool--lib.sh scriptlet.
http://thread.gmane.org/gmane.comp.version-control.git/134906/focus=135006
Signed-off-by: David Aguilar <davvid@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
17 files changed:
Makefile | patch | blob | history | |
git-mergetool--lib.sh | patch | blob | history | |
mergetools/araxis | [new file with mode: 0644] | patch | blob |
mergetools/bc3 | [new file with mode: 0644] | patch | blob |
mergetools/defaults | [new file with mode: 0644] | patch | blob |
mergetools/diffuse | [new file with mode: 0644] | patch | blob |
mergetools/ecmerge | [new file with mode: 0644] | patch | blob |
mergetools/emerge | [new file with mode: 0644] | patch | blob |
mergetools/kdiff3 | [new file with mode: 0644] | patch | blob |
mergetools/kompare | [new file with mode: 0644] | patch | blob |
mergetools/meld | [new file with mode: 0644] | patch | blob |
mergetools/opendiff | [new file with mode: 0644] | patch | blob |
mergetools/p4merge | [new file with mode: 0644] | patch | blob |
mergetools/tkdiff | [new file with mode: 0644] | patch | blob |
mergetools/tortoisemerge | [new file with mode: 0644] | patch | blob |
mergetools/vim | [new file with mode: 0644] | patch | blob |
mergetools/xxdiff | [new file with mode: 0644] | patch | blob |
diff --git a/Makefile b/Makefile
index 89cc6245a721a1cb807e197fb3346cec02367a51..1e91b19c4d7167e69d8fe84cda49419ca52280d9 100644 (file)
--- a/Makefile
+++ b/Makefile
mandir = share/man
infodir = share/info
gitexecdir = libexec/git-core
+mergetoolsdir = $(gitexecdir)/mergetools
sharedir = $(prefix)/share
gitwebdir = $(sharedir)/gitweb
template_dir = share/git-core/templates
gitexec_instdir_SQ = $(subst ','\'',$(gitexec_instdir))
export gitexec_instdir
+ifneq ($(filter /%,$(firstword $(mergetoolsdir))),)
+mergetools_instdir = $(mergetoolsdir)
+else
+mergetools_instdir = $(prefix)/$(mergetoolsdir)
+endif
+mergetools_instdir_SQ = $(subst ','\'',$(mergetools_instdir))
+
install_bindir_programs := $(patsubst %,%$X,$(BINDIR_PROGRAMS_NEED_X)) $(BINDIR_PROGRAMS_NO_X)
install: all
$(INSTALL) -m 644 $(SCRIPT_LIB) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) $(install_bindir_programs) '$(DESTDIR_SQ)$(bindir_SQ)'
$(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(mergetools_instdir_SQ)'
+ (cd mergetools && $(TAR) cf - .) | \
+ (cd '$(DESTDIR_SQ)$(mergetools_instdir_SQ)' && umask 022 && $(TAR) xof -)
ifndef NO_PERL
$(MAKE) -C perl prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
$(MAKE) -C gitweb install
diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
index 5820a6354a706324c755f31df71f328122f7a45b..8fc65d0400545e30fd56f890e6b17052f54f857c 100644 (file)
--- a/git-mergetool--lib.sh
+++ b/git-mergetool--lib.sh
}
translate_merge_tool_path () {
- case "$1" in
- araxis)
- echo compare
- ;;
- bc3)
- echo bcompare
- ;;
- emerge)
- echo emacs
- ;;
- gvimdiff|gvimdiff2)
- echo gvim
- ;;
- vimdiff|vimdiff2)
- echo vim
- ;;
- *)
- echo "$1"
- ;;
- esac
+ echo "$1"
}
check_unchanged () {
fi
}
+valid_tool_config () {
+ if test -n "$(get_merge_tool_cmd "$1")"
+ then
+ return 0
+ else
+ return 1
+ fi
+}
+
valid_tool () {
+ setup_tool "$1" || valid_tool_config "$1"
+}
+
+setup_tool () {
case "$1" in
- araxis | bc3 | diffuse | ecmerge | emerge | gvimdiff | gvimdiff2 | \
- kdiff3 | meld | opendiff | p4merge | tkdiff | vimdiff | vimdiff2 | xxdiff)
- ;; # happy
- kompare)
- if ! diff_mode
- then
- return 1
- fi
- ;;
- tortoisemerge)
- if ! merge_mode
- then
- return 1
- fi
+ vim*|gvim*)
+ tool=vim
;;
*)
- if test -z "$(get_merge_tool_cmd "$1")"
- then
- return 1
- fi
+ tool="$1"
;;
esac
+ mergetools="$(git --exec-path)/mergetools"
+
+ # Load the default definitions
+ . "$mergetools/defaults"
+ if ! test -f "$mergetools/$tool"
+ then
+ return 1
+ fi
+
+ # Load the redefined functions
+ . "$mergetools/$tool"
+
+ if merge_mode && ! can_merge
+ then
+ echo "error: '$tool' can not be used to resolve merges" >&2
+ exit 1
+ elif diff_mode && ! can_diff
+ then
+ echo "error: '$tool' can only be used to resolve merges" >&2
+ exit 1
+ fi
+ return 0
}
get_merge_tool_cmd () {
# Prints the custom command for a merge tool
- if test -n "$1"
- then
- merge_tool="$1"
- else
- merge_tool="$(get_merge_tool)"
- fi
+ merge_tool="$1"
if diff_mode
then
echo "$(git config difftool.$merge_tool.cmd ||
fi
}
+# Entry point for running tools
run_merge_tool () {
# If GIT_PREFIX is empty then we cannot use it in tools
# that expect to be able to chdir() to its value.
base_present="$2"
status=0
- case "$1" in
- araxis)
- if merge_mode
- then
- touch "$BACKUP"
- if $base_present
- then
- "$merge_tool_path" -wait -merge -3 -a1 \
- "$BASE" "$LOCAL" "$REMOTE" "$MERGED" \
- >/dev/null 2>&1
- else
- "$merge_tool_path" -wait -2 \
- "$LOCAL" "$REMOTE" "$MERGED" \
- >/dev/null 2>&1
- fi
- check_unchanged
- else
- "$merge_tool_path" -wait -2 "$LOCAL" "$REMOTE" \
- >/dev/null 2>&1
- fi
- ;;
- bc3)
- if merge_mode
- then
- touch "$BACKUP"
- if $base_present
- then
- "$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" \
- -mergeoutput="$MERGED"
- else
- "$merge_tool_path" "$LOCAL" "$REMOTE" \
- -mergeoutput="$MERGED"
- fi
- check_unchanged
- else
- "$merge_tool_path" "$LOCAL" "$REMOTE"
- fi
- ;;
- diffuse)
- if merge_mode
- then
- touch "$BACKUP"
- if $base_present
- then
- "$merge_tool_path" \
- "$LOCAL" "$MERGED" "$REMOTE" \
- "$BASE" | cat
- else
- "$merge_tool_path" \
- "$LOCAL" "$MERGED" "$REMOTE" | cat
- fi
- check_unchanged
- else
- "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
- fi
- ;;
- ecmerge)
- if merge_mode
- then
- touch "$BACKUP"
- if $base_present
- then
- "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" \
- --default --mode=merge3 --to="$MERGED"
- else
- "$merge_tool_path" "$LOCAL" "$REMOTE" \
- --default --mode=merge2 --to="$MERGED"
- fi
- check_unchanged
- else
- "$merge_tool_path" --default --mode=diff2 \
- "$LOCAL" "$REMOTE"
- fi
- ;;
- emerge)
- if merge_mode
- then
- if $base_present
- then
- "$merge_tool_path" \
- -f emerge-files-with-ancestor-command \
- "$LOCAL" "$REMOTE" "$BASE" \
- "$(basename "$MERGED")"
- else
- "$merge_tool_path" \
- -f emerge-files-command \
- "$LOCAL" "$REMOTE" \
- "$(basename "$MERGED")"
- fi
- status=$?
- else
- "$merge_tool_path" -f emerge-files-command \
- "$LOCAL" "$REMOTE"
- fi
- ;;
- gvimdiff|vimdiff)
- if merge_mode
- then
- touch "$BACKUP"
- if $base_present
- then
- "$merge_tool_path" -f -d -c "wincmd J" \
- "$MERGED" "$LOCAL" "$BASE" "$REMOTE"
- else
- "$merge_tool_path" -f -d -c "wincmd l" \
- "$LOCAL" "$MERGED" "$REMOTE"
- fi
- check_unchanged
- else
- "$merge_tool_path" -R -f -d -c "wincmd l" \
- -c 'cd $GIT_PREFIX' \
- "$LOCAL" "$REMOTE"
- fi
- ;;
- gvimdiff2|vimdiff2)
- if merge_mode
- then
- touch "$BACKUP"
- "$merge_tool_path" -f -d -c "wincmd l" \
- "$LOCAL" "$MERGED" "$REMOTE"
- check_unchanged
- else
- "$merge_tool_path" -R -f -d -c "wincmd l" \
- -c 'cd $GIT_PREFIX' \
- "$LOCAL" "$REMOTE"
- fi
- ;;
- kdiff3)
- if merge_mode
- then
- if $base_present
- then
- "$merge_tool_path" --auto \
- --L1 "$MERGED (Base)" \
- --L2 "$MERGED (Local)" \
- --L3 "$MERGED (Remote)" \
- -o "$MERGED" \
- "$BASE" "$LOCAL" "$REMOTE" \
- >/dev/null 2>&1
- else
- "$merge_tool_path" --auto \
- --L1 "$MERGED (Local)" \
- --L2 "$MERGED (Remote)" \
- -o "$MERGED" \
- "$LOCAL" "$REMOTE" \
- >/dev/null 2>&1
- fi
- status=$?
- else
- "$merge_tool_path" --auto \
- --L1 "$MERGED (A)" \
- --L2 "$MERGED (B)" "$LOCAL" "$REMOTE" \
- >/dev/null 2>&1
- fi
- ;;
- kompare)
- "$merge_tool_path" "$LOCAL" "$REMOTE"
- ;;
- meld)
- if merge_mode
- then
- touch "$BACKUP"
- "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
- check_unchanged
- else
- "$merge_tool_path" "$LOCAL" "$REMOTE"
- fi
- ;;
- opendiff)
- if merge_mode
- then
- touch "$BACKUP"
- if $base_present
- then
- "$merge_tool_path" "$LOCAL" "$REMOTE" \
- -ancestor "$BASE" \
- -merge "$MERGED" | cat
- else
- "$merge_tool_path" "$LOCAL" "$REMOTE" \
- -merge "$MERGED" | cat
- fi
- check_unchanged
- else
- "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
- fi
- ;;
- p4merge)
- if merge_mode
- then
- touch "$BACKUP"
- $base_present || >"$BASE"
- "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
- check_unchanged
- else
- "$merge_tool_path" "$LOCAL" "$REMOTE"
- fi
- ;;
- tkdiff)
- if merge_mode
- then
- if $base_present
- then
- "$merge_tool_path" -a "$BASE" \
- -o "$MERGED" "$LOCAL" "$REMOTE"
- else
- "$merge_tool_path" \
- -o "$MERGED" "$LOCAL" "$REMOTE"
- fi
- status=$?
- else
- "$merge_tool_path" "$LOCAL" "$REMOTE"
- fi
- ;;
- tortoisemerge)
- if $base_present
- then
- touch "$BACKUP"
- "$merge_tool_path" \
- -base:"$BASE" -mine:"$LOCAL" \
- -theirs:"$REMOTE" -merged:"$MERGED"
- check_unchanged
- else
- echo "TortoiseMerge cannot be used without a base" 1>&2
- status=1
- fi
- ;;
- xxdiff)
- if merge_mode
- then
- touch "$BACKUP"
- if $base_present
- then
- "$merge_tool_path" -X --show-merged-pane \
- -R 'Accel.SaveAsMerged: "Ctrl-S"' \
- -R 'Accel.Search: "Ctrl+F"' \
- -R 'Accel.SearchForward: "Ctrl-G"' \
- --merged-file "$MERGED" \
- "$LOCAL" "$BASE" "$REMOTE"
- else
- "$merge_tool_path" -X $extra \
- -R 'Accel.SaveAsMerged: "Ctrl-S"' \
- -R 'Accel.Search: "Ctrl+F"' \
- -R 'Accel.SearchForward: "Ctrl-G"' \
- --merged-file "$MERGED" \
- "$LOCAL" "$REMOTE"
- fi
- check_unchanged
- else
- "$merge_tool_path" \
- -R 'Accel.Search: "Ctrl+F"' \
- -R 'Accel.SearchForward: "Ctrl-G"' \
- "$LOCAL" "$REMOTE"
- fi
- ;;
- *)
- merge_tool_cmd="$(get_merge_tool_cmd "$1")"
- if test -z "$merge_tool_cmd"
- then
- if merge_mode
- then
- status=1
- fi
- break
- fi
- if merge_mode
- then
- trust_exit_code="$(git config --bool \
- mergetool."$1".trustExitCode || echo false)"
- if test "$trust_exit_code" = "false"
- then
- touch "$BACKUP"
- ( eval $merge_tool_cmd )
- check_unchanged
- else
- ( eval $merge_tool_cmd )
- status=$?
- fi
- else
- ( eval $merge_tool_cmd )
- fi
- ;;
- esac
+ # Bring tool-specific functions into scope
+ setup_tool "$1"
+
+ if merge_mode
+ then
+ merge_cmd "$1"
+ else
+ diff_cmd "$1"
+ fi
return $status
}
get_merge_tool_path () {
# A merge tool has been set, so verify that it's valid.
- if test -n "$1"
- then
- merge_tool="$1"
- else
- merge_tool="$(get_merge_tool)"
- fi
+ merge_tool="$1"
if ! valid_tool "$merge_tool"
then
echo >&2 "Unknown merge tool $merge_tool"
get_merge_tool () {
# Check if a merge tool has been configured
- merge_tool=$(get_configured_merge_tool)
+ merge_tool="$(get_configured_merge_tool)"
# Try to guess an appropriate merge tool if no tool has been set.
if test -z "$merge_tool"
then
diff --git a/mergetools/araxis b/mergetools/araxis
--- /dev/null
+++ b/mergetools/araxis
@@ -0,0 +1,20 @@
+diff_cmd () {
+ "$merge_tool_path" -wait -2 "$LOCAL" "$REMOTE" >/dev/null 2>&1
+}
+
+merge_cmd () {
+ touch "$BACKUP"
+ if $base_present
+ then
+ "$merge_tool_path" -wait -merge -3 -a1 \
+ "$BASE" "$LOCAL" "$REMOTE" "$MERGED" >/dev/null 2>&1
+ else
+ "$merge_tool_path" -wait -2 \
+ "$LOCAL" "$REMOTE" "$MERGED" >/dev/null 2>&1
+ fi
+ check_unchanged
+}
+
+translate_merge_tool_path() {
+ echo compare
+}
diff --git a/mergetools/bc3 b/mergetools/bc3
--- /dev/null
+++ b/mergetools/bc3
@@ -0,0 +1,20 @@
+diff_cmd () {
+ "$merge_tool_path" "$LOCAL" "$REMOTE"
+}
+
+merge_cmd () {
+ touch "$BACKUP"
+ if $base_present
+ then
+ "$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" \
+ -mergeoutput="$MERGED"
+ else
+ "$merge_tool_path" "$LOCAL" "$REMOTE" \
+ -mergeoutput="$MERGED"
+ fi
+ check_unchanged
+}
+
+translate_merge_tool_path() {
+ echo bcompare
+}
diff --git a/mergetools/defaults b/mergetools/defaults
--- /dev/null
+++ b/mergetools/defaults
@@ -0,0 +1,46 @@
+# Redefined by builtin tools
+can_merge () {
+ return 0
+}
+
+can_diff () {
+ return 0
+}
+
+diff_cmd () {
+ merge_tool_cmd="$(get_merge_tool_cmd "$1")"
+ if test -z "$merge_tool_cmd"
+ then
+ status=1
+ break
+ fi
+ ( eval $merge_tool_cmd )
+ status=$?
+ return $status
+}
+
+merge_cmd () {
+ merge_tool_cmd="$(get_merge_tool_cmd "$1")"
+ if test -z "$merge_tool_cmd"
+ then
+ status=1
+ break
+ fi
+ trust_exit_code="$(git config --bool \
+ mergetool."$1".trustExitCode || echo false)"
+ if test "$trust_exit_code" = "false"
+ then
+ touch "$BACKUP"
+ ( eval $merge_tool_cmd )
+ status=$?
+ check_unchanged
+ else
+ ( eval $merge_tool_cmd )
+ status=$?
+ fi
+ return $status
+}
+
+translate_merge_tool_path () {
+ echo "$1"
+}
diff --git a/mergetools/diffuse b/mergetools/diffuse
--- /dev/null
+++ b/mergetools/diffuse
@@ -0,0 +1,17 @@
+diff_cmd () {
+ "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
+}
+
+merge_cmd () {
+ touch "$BACKUP"
+ if $base_present
+ then
+ "$merge_tool_path" \
+ "$LOCAL" "$MERGED" "$REMOTE" \
+ "$BASE" | cat
+ else
+ "$merge_tool_path" \
+ "$LOCAL" "$MERGED" "$REMOTE" | cat
+ fi
+ check_unchanged
+}
diff --git a/mergetools/ecmerge b/mergetools/ecmerge
--- /dev/null
+++ b/mergetools/ecmerge
@@ -0,0 +1,16 @@
+diff_cmd () {
+ "$merge_tool_path" --default --mode=diff2 "$LOCAL" "$REMOTE"
+}
+
+merge_cmd () {
+ touch "$BACKUP"
+ if $base_present
+ then
+ "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" \
+ --default --mode=merge3 --to="$MERGED"
+ else
+ "$merge_tool_path" "$LOCAL" "$REMOTE" \
+ --default --mode=merge2 --to="$MERGED"
+ fi
+ check_unchanged
+}
diff --git a/mergetools/emerge b/mergetools/emerge
--- /dev/null
+++ b/mergetools/emerge
@@ -0,0 +1,23 @@
+diff_cmd () {
+ "$merge_tool_path" -f emerge-files-command "$LOCAL" "$REMOTE"
+}
+
+merge_cmd () {
+ if $base_present
+ then
+ "$merge_tool_path" \
+ -f emerge-files-with-ancestor-command \
+ "$LOCAL" "$REMOTE" "$BASE" \
+ "$(basename "$MERGED")"
+ else
+ "$merge_tool_path" \
+ -f emerge-files-command \
+ "$LOCAL" "$REMOTE" \
+ "$(basename "$MERGED")"
+ fi
+ status=$?
+}
+
+translate_merge_tool_path() {
+ echo emacs
+}
diff --git a/mergetools/kdiff3 b/mergetools/kdiff3
--- /dev/null
+++ b/mergetools/kdiff3
@@ -0,0 +1,24 @@
+diff_cmd () {
+ "$merge_tool_path" --auto \
+ --L1 "$MERGED (A)" --L2 "$MERGED (B)" \
+ "$LOCAL" "$REMOTE" >/dev/null 2>&1
+}
+
+merge_cmd () {
+ if $base_present
+ then
+ "$merge_tool_path" --auto \
+ --L1 "$MERGED (Base)" \
+ --L2 "$MERGED (Local)" \
+ --L3 "$MERGED (Remote)" \
+ -o "$MERGED" "$BASE" "$LOCAL" "$REMOTE" \
+ >/dev/null 2>&1
+ else
+ "$merge_tool_path" --auto \
+ --L1 "$MERGED (Local)" \
+ --L2 "$MERGED (Remote)" \
+ -o "$MERGED" "$LOCAL" "$REMOTE" \
+ >/dev/null 2>&1
+ fi
+ status=$?
+}
diff --git a/mergetools/kompare b/mergetools/kompare
--- /dev/null
+++ b/mergetools/kompare
@@ -0,0 +1,7 @@
+can_merge () {
+ return 1
+}
+
+diff_cmd () {
+ "$merge_tool_path" "$LOCAL" "$REMOTE"
+}
diff --git a/mergetools/meld b/mergetools/meld
--- /dev/null
+++ b/mergetools/meld
@@ -0,0 +1,9 @@
+diff_cmd () {
+ "$merge_tool_path" "$LOCAL" "$REMOTE"
+}
+
+merge_cmd () {
+ touch "$BACKUP"
+ "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
+ check_unchanged
+}
diff --git a/mergetools/opendiff b/mergetools/opendiff
--- /dev/null
+++ b/mergetools/opendiff
@@ -0,0 +1,16 @@
+diff_cmd () {
+ "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
+}
+
+merge_cmd () {
+ touch "$BACKUP"
+ if $base_present
+ then
+ "$merge_tool_path" "$LOCAL" "$REMOTE" \
+ -ancestor "$BASE" -merge "$MERGED" | cat
+ else
+ "$merge_tool_path" "$LOCAL" "$REMOTE" \
+ -merge "$MERGED" | cat
+ fi
+ check_unchanged
+}
diff --git a/mergetools/p4merge b/mergetools/p4merge
--- /dev/null
+++ b/mergetools/p4merge
@@ -0,0 +1,10 @@
+diff_cmd () {
+ "$merge_tool_path" "$LOCAL" "$REMOTE"
+}
+
+merge_cmd () {
+ touch "$BACKUP"
+ $base_present || >"$BASE"
+ "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
+ check_unchanged
+}
diff --git a/mergetools/tkdiff b/mergetools/tkdiff
--- /dev/null
+++ b/mergetools/tkdiff
@@ -0,0 +1,12 @@
+diff_cmd () {
+ "$merge_tool_path" "$LOCAL" "$REMOTE"
+}
+
+merge_cmd () {
+ if $base_present
+ then
+ "$merge_tool_path" -a "$BASE" -o "$MERGED" "$LOCAL" "$REMOTE"
+ else
+ "$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"
+ fi
+}
diff --git a/mergetools/tortoisemerge b/mergetools/tortoisemerge
--- /dev/null
+++ b/mergetools/tortoisemerge
@@ -0,0 +1,17 @@
+can_diff () {
+ return 1
+}
+
+merge_cmd () {
+ if $base_present
+ then
+ touch "$BACKUP"
+ "$merge_tool_path" \
+ -base:"$BASE" -mine:"$LOCAL" \
+ -theirs:"$REMOTE" -merged:"$MERGED"
+ check_unchanged
+ else
+ echo "TortoiseMerge cannot be used without a base" 1>&2
+ return 1
+ fi
+}
diff --git a/mergetools/vim b/mergetools/vim
--- /dev/null
+++ b/mergetools/vim
@@ -0,0 +1,44 @@
+diff_cmd () {
+ case "$1" in
+ gvimdiff|vimdiff)
+ "$merge_tool_path" -R -f -d \
+ -c 'wincmd l' -c 'cd $GIT_PREFIX' "$LOCAL" "$REMOTE"
+ ;;
+ gvimdiff2|vimdiff2)
+ "$merge_tool_path" -R -f -d \
+ -c 'wincmd l' -c 'cd $GIT_PREFIX' "$LOCAL" "$REMOTE"
+ ;;
+ esac
+}
+
+merge_cmd () {
+ touch "$BACKUP"
+ case "$1" in
+ gvimdiff|vimdiff)
+ if $base_present
+ then
+ "$merge_tool_path" -f -d -c 'wincmd J' \
+ "$MERGED" "$LOCAL" "$BASE" "$REMOTE"
+ else
+ "$merge_tool_path" -f -d -c 'wincmd l' \
+ "$LOCAL" "$MERGED" "$REMOTE"
+ fi
+ ;;
+ gvimdiff2|vimdiff2)
+ "$merge_tool_path" -f -d -c 'wincmd l' \
+ "$LOCAL" "$MERGED" "$REMOTE"
+ ;;
+ esac
+ check_unchanged
+}
+
+translate_merge_tool_path() {
+ case "$1" in
+ gvimdiff|gvimdiff2)
+ echo gvim
+ ;;
+ vimdiff|vimdiff2)
+ echo vim
+ ;;
+ esac
+}
diff --git a/mergetools/xxdiff b/mergetools/xxdiff
--- /dev/null
+++ b/mergetools/xxdiff
@@ -0,0 +1,25 @@
+diff_cmd () {
+ "$merge_tool_path" \
+ -R 'Accel.Search: "Ctrl+F"' \
+ -R 'Accel.SearchForward: "Ctrl-G"' \
+ "$LOCAL" "$REMOTE"
+}
+
+merge_cmd () {
+ touch "$BACKUP"
+ if $base_present
+ then
+ "$merge_tool_path" -X --show-merged-pane \
+ -R 'Accel.SaveAsMerged: "Ctrl-S"' \
+ -R 'Accel.Search: "Ctrl+F"' \
+ -R 'Accel.SearchForward: "Ctrl-G"' \
+ --merged-file "$MERGED" "$LOCAL" "$BASE" "$REMOTE"
+ else
+ "$merge_tool_path" -X $extra \
+ -R 'Accel.SaveAsMerged: "Ctrl-S"' \
+ -R 'Accel.Search: "Ctrl+F"' \
+ -R 'Accel.SearchForward: "Ctrl-G"' \
+ --merged-file "$MERGED" "$LOCAL" "$REMOTE"
+ fi
+ check_unchanged
+}