[RFC/PATCH] git-mergetool: allow using merge tools for staging changes

From: David Aguilar <hidden>
Date: 2016-06-15 22:45:16
Subsystem: the rest · Maintainer: Linus Torvalds

git-mergetool contains a lot of useful code for interfacing
with arbitrary diff/merge tools.  This code is only ever used
when merge conflicts occur, though.

This change allows git-mergetool to be used for the common
task of comparing unstaged changes against the latest commit.
Being able to see side-by-side diffs in your favorite $mergetool
is the benefit of these changes.

When additional changes are staged in the index, those changes
are provided as the $BASE merge file.

Signed-off-by: David Aguilar <redacted>
---

Notes:

I am aware that git-citool is a viable alternative in such a
scenario, but being able to see a side-by-side diff is one of
the first things that CVS-using co-workers asked me about
when using git.

This only affects the "git mergetool -t <tool> <file(s)>"
scenario.  The behavior of the no-argument "git mergetool"
invocation is unchanged.

Style note:

This patch mixes tabs and spaces (indent: 4) to be consistent
with the rest of git-mergetool.sh.

 git-mergetool.sh |   32 ++++++++++++++++++++++++++------
 1 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/git-mergetool.sh b/git-mergetool.sh
index 94187c3..9e5cc68 100755
--- a/git-mergetool.sh
+++ b/git-mergetool.sh
@@ -131,6 +131,13 @@ merge_file () {
     MERGED="$1"
 
     f=`git ls-files -u -- "$MERGED"`
+
+    if test -z "$f" ; then
+	f=$(git ls-files --modified -- "$MERGED")
+	test -z "$f" && f=$(git diff --name-only --cached -- "$MERGED")
+	test -f "$f" && worktree_mode=1
+    fi
+
     if test -z "$f" ; then
 	if test ! -f "$MERGED" ; then
 	    echo "$MERGED: file not found"
@@ -149,13 +156,26 @@ merge_file () {
     mv -- "$MERGED" "$BACKUP"
     cp -- "$BACKUP" "$MERGED"
 
-    base_mode=`git ls-files -u -- "$MERGED" | awk '{if ($3==1) print $1;}'`
-    local_mode=`git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $1;}'`
-    remote_mode=`git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $1;}'`
+    if test -n "$worktree_mode" ; then
+	base_mode=$(git diff --name-only --cached -- "$MERGED")
+	local_mode=1
+	remote_mode=1
+	cp "$MERGED" "$LOCAL"
+	git show HEAD:"$MERGED" > "$REMOTE"
+	if base_present ; then
+	    # If changes are present in the index use them as $BASE
+	    git checkout-index --prefix=.remote- "$MERGED"
+	    mv .remote-"$MERGED" "$BASE"
+	fi
+    else
+	base_mode=`git ls-files -u -- "$MERGED" | awk '{if ($3==1) print $1;}'`
+	local_mode=`git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $1;}'`
+	remote_mode=`git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $1;}'`
 
-    base_present   && git cat-file blob ":1:$prefix$MERGED" >"$BASE" 2>/dev/null
-    local_present  && git cat-file blob ":2:$prefix$MERGED" >"$LOCAL" 2>/dev/null
-    remote_present && git cat-file blob ":3:$prefix$MERGED" >"$REMOTE" 2>/dev/null
+	base_present   && git cat-file blob ":1:$prefix$MERGED" >"$BASE" 2>/dev/null
+	local_present  && git cat-file blob ":2:$prefix$MERGED" >"$LOCAL" 2>/dev/null
+	remote_present && git cat-file blob ":3:$prefix$MERGED" >"$REMOTE" 2>/dev/null
+    fi
 
     if test -z "$local_mode" -o -z "$remote_mode"; then
 	echo "Deleted merge conflict for '$MERGED':"
-- 
1.6.0.1.161.g7f314
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help