Skip to content

Commit

Permalink
mergetool: Use args as pathspec to unmerged files
Browse files Browse the repository at this point in the history
Mergetool now treats its path arguments as a pathspec (like other git
subcommands), restricting action to the given files and directories.
Files matching the pathspec are filtered so mergetool only acts on
unmerged paths; previously it would assume each path argument was in an
unresolved state, and get confused when it couldn't check out their
other stages.

Running "git mergetool subdir" will prompt to resolve all conflicted
blobs under subdir.

Signed-off-by: Jonathon Mah <me@JonathonMah.com>
Acked-by: David Aguilar <davvid@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jonathon Mah authored and Junio C Hamano committed Sep 26, 2011
1 parent 2765233 commit 3e8e691
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 69 deletions.
7 changes: 4 additions & 3 deletions Documentation/git-mergetool.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ Use `git mergetool` to run one of several merge utilities to resolve
merge conflicts. It is typically run after 'git merge'.

If one or more <file> parameters are given, the merge tool program will
be run to resolve differences on each file. If no <file> names are
specified, 'git mergetool' will run the merge tool program on every file
with merge conflicts.
be run to resolve differences on each file (skipping those without
conflicts). Specifying a directory will include all unresolved files in
that path. If no <file> names are specified, 'git mergetool' will run
the merge tool program on every file with merge conflicts.

OPTIONS
-------
Expand Down
76 changes: 28 additions & 48 deletions git-mergetool.sh
Original file line number Diff line number Diff line change
Expand Up @@ -342,64 +342,44 @@ merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo fa

last_status=0
rollup_status=0
rerere=false

files_to_merge() {
if test "$rerere" = true
then
git rerere remaining
else
git ls-files -u | sed -e 's/^[^ ]* //' | sort -u
fi
}

files=

if test $# -eq 0 ; then
cd_to_toplevel

if test -e "$GIT_DIR/MERGE_RR"
then
rerere=true
files=$(git rerere remaining)
else
files=$(git ls-files -u | sed -e 's/^[^ ]* //' | sort -u)
fi
else
files=$(git ls-files -u -- "$@" | sed -e 's/^[^ ]* //' | sort -u)
fi

files=$(files_to_merge)
if test -z "$files" ; then
echo "No files need merging"
exit 0
fi
if test -z "$files" ; then
echo "No files need merging"
exit 0
fi

# Save original stdin
exec 3<&0
# Save original stdin
exec 3<&0

printf "Merging:\n"
printf "$files\n"
printf "Merging:\n"
printf "$files\n"

files_to_merge |
while IFS= read i
do
if test $last_status -ne 0; then
prompt_after_failed_merge <&3 || exit 1
fi
printf "\n"
merge_file "$i" <&3
last_status=$?
if test $last_status -ne 0; then
rollup_status=1
fi
done
else
while test $# -gt 0; do
if test $last_status -ne 0; then
prompt_after_failed_merge || exit 1
fi
printf "\n"
merge_file "$1"
last_status=$?
if test $last_status -ne 0; then
rollup_status=1
fi
shift
done
fi
IFS='
'; for i in $files
do
if test $last_status -ne 0; then
prompt_after_failed_merge <&3 || exit 1
fi
printf "\n"
merge_file "$i" <&3
last_status=$?
if test $last_status -ne 0; then
rollup_status=1
fi
done

exit $rollup_status
58 changes: 40 additions & 18 deletions t/t7610-mergetool.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Testing basic merge tool invocation'
test_expect_success 'setup' '
git config rerere.enabled true &&
echo master >file1 &&
echo master spaced >"spaced name" &&
echo master file11 >file11 &&
echo master file12 >file12 &&
echo master file13 >file13 &&
Expand All @@ -30,13 +31,14 @@ test_expect_success 'setup' '
git commit -m "Add foo"
) &&
git submodule add git://example.com/submod submod &&
git add file1 file1[1-4] subdir/file3 .gitmodules submod &&
git add file1 "spaced name" file1[1-4] subdir/file3 .gitmodules submod &&
git commit -m "add initial versions" &&
git checkout -b branch1 master &&
git submodule update -N &&
echo branch1 change >file1 &&
echo branch1 newfile >file2 &&
echo branch1 spaced >"spaced name" &&
echo branch1 change file11 >file11 &&
echo branch1 change file13 >file13 &&
echo branch1 sub >subdir/file3 &&
Expand All @@ -47,14 +49,15 @@ test_expect_success 'setup' '
git commit -m "Add bar on branch1" &&
git checkout -b submod-branch1
) &&
git add file1 file11 file13 file2 subdir/file3 submod &&
git add file1 "spaced name" file11 file13 file2 subdir/file3 submod &&
git rm file12 &&
git commit -m "branch1 changes" &&
git checkout master &&
git submodule update -N &&
echo master updated >file1 &&
echo master new >file2 &&
echo master updated spaced >"spaced name" &&
echo master updated file12 >file12 &&
echo master updated file14 >file14 &&
echo master new sub >subdir/file3 &&
Expand All @@ -65,7 +68,7 @@ test_expect_success 'setup' '
git commit -m "Add bar on master" &&
git checkout -b submod-master
) &&
git add file1 file12 file14 file2 subdir/file3 submod &&
git add file1 "spaced name" file12 file14 file2 subdir/file3 submod &&
git rm file11 &&
git commit -m "master updates" &&
Expand All @@ -78,8 +81,8 @@ test_expect_success 'custom mergetool' '
git checkout -b test1 branch1 &&
git submodule update -N &&
test_must_fail git merge master >/dev/null 2>&1 &&
( yes "" | git mergetool file1 >/dev/null 2>&1 ) &&
( yes "" | git mergetool file2 >/dev/null 2>&1 ) &&
( yes "" | git mergetool file1 file1 ) &&
( yes "" | git mergetool file2 "spaced name" >/dev/null 2>&1 ) &&
( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
Expand All @@ -97,6 +100,7 @@ test_expect_success 'mergetool crlf' '
test_must_fail git merge master >/dev/null 2>&1 &&
( yes "" | git mergetool file1 >/dev/null 2>&1 ) &&
( yes "" | git mergetool file2 >/dev/null 2>&1 ) &&
( yes "" | git mergetool "spaced name" >/dev/null 2>&1 ) &&
( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
Expand Down Expand Up @@ -126,7 +130,7 @@ test_expect_success 'mergetool on file in parent dir' '
(
cd subdir &&
( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) &&
( yes "" | git mergetool ../file2 >/dev/null 2>&1 ) &&
( yes "" | git mergetool ../file2 ../spaced\ name >/dev/null 2>&1 ) &&
( yes "d" | git mergetool ../file11 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool ../file12 >/dev/null 2>&1 ) &&
( yes "l" | git mergetool ../submod >/dev/null 2>&1 ) &&
Expand Down Expand Up @@ -180,6 +184,24 @@ test_expect_success 'mergetool skips resolved paths when rerere is active' '
git reset --hard
'

test_expect_success 'mergetool takes partial path' '
git config rerere.enabled false &&
git checkout -b test12 branch1 &&
git submodule update -N &&
test_must_fail git merge master &&
#shouldnt need these lines
#( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
#( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
#( yes "l" | git mergetool submod >/dev/null 2>&1 ) &&
#( yes "" | git mergetool file1 file2 >/dev/null 2>&1 ) &&
( yes "" | git mergetool subdir ) &&
test "$(cat subdir/file3)" = "master new sub" &&
git reset --hard
'

test_expect_success 'deleted vs modified submodule' '
git checkout -b test6 branch1 &&
git submodule update -N &&
Expand All @@ -189,7 +211,7 @@ test_expect_success 'deleted vs modified submodule' '
git checkout -b test6.a test6 &&
test_must_fail git merge master &&
test -n "$(git ls-files -u)" &&
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "r" | git mergetool submod ) &&
rmdir submod && mv submod-movedaside submod &&
Expand All @@ -205,7 +227,7 @@ test_expect_success 'deleted vs modified submodule' '
git submodule update -N &&
test_must_fail git merge master &&
test -n "$(git ls-files -u)" &&
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "l" | git mergetool submod ) &&
test ! -e submod &&
Expand All @@ -218,7 +240,7 @@ test_expect_success 'deleted vs modified submodule' '
git submodule update -N &&
test_must_fail git merge test6 &&
test -n "$(git ls-files -u)" &&
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "r" | git mergetool submod ) &&
test ! -e submod &&
Expand All @@ -233,7 +255,7 @@ test_expect_success 'deleted vs modified submodule' '
git submodule update -N &&
test_must_fail git merge test6 &&
test -n "$(git ls-files -u)" &&
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "l" | git mergetool submod ) &&
test "$(cat submod/bar)" = "master submodule" &&
Expand All @@ -256,7 +278,7 @@ test_expect_success 'file vs modified submodule' '
git checkout -b test7.a branch1 &&
test_must_fail git merge master &&
test -n "$(git ls-files -u)" &&
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "r" | git mergetool submod ) &&
rmdir submod && mv submod-movedaside submod &&
Expand All @@ -271,7 +293,7 @@ test_expect_success 'file vs modified submodule' '
git checkout -b test7.b test7 &&
test_must_fail git merge master &&
test -n "$(git ls-files -u)" &&
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "l" | git mergetool submod ) &&
git submodule update -N &&
Expand All @@ -286,7 +308,7 @@ test_expect_success 'file vs modified submodule' '
git submodule update -N &&
test_must_fail git merge test7 &&
test -n "$(git ls-files -u)" &&
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "r" | git mergetool submod ) &&
test -d submod.orig &&
Expand All @@ -301,7 +323,7 @@ test_expect_success 'file vs modified submodule' '
git submodule update -N &&
test_must_fail git merge test7 &&
test -n "$(git ls-files -u)" &&
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "l" | git mergetool submod ) &&
test "$(cat submod/bar)" = "master submodule" &&
Expand Down Expand Up @@ -388,7 +410,7 @@ test_expect_success 'directory vs modified submodule' '
test "$(cat submod/file16)" = "not a submodule" &&
rm -rf submod.orig &&
git reset --hard &&
git reset --hard >/dev/null 2>&1 &&
test_must_fail git merge master &&
test -n "$(git ls-files -u)" &&
test ! -e submod.orig &&
Expand All @@ -400,7 +422,7 @@ test_expect_success 'directory vs modified submodule' '
( cd submod && git clean -f && git reset --hard ) &&
git submodule update -N &&
test "$(cat submod/bar)" = "master submodule" &&
git reset --hard && rm -rf submod-movedaside &&
git reset --hard >/dev/null 2>&1 && rm -rf submod-movedaside &&
git checkout -b test11.c master &&
git submodule update -N &&
Expand All @@ -410,15 +432,15 @@ test_expect_success 'directory vs modified submodule' '
git submodule update -N &&
test "$(cat submod/bar)" = "master submodule" &&
git reset --hard &&
git reset --hard >/dev/null 2>&1 &&
git submodule update -N &&
test_must_fail git merge test11 &&
test -n "$(git ls-files -u)" &&
test ! -e submod.orig &&
( yes "r" | git mergetool submod ) &&
test "$(cat submod/file16)" = "not a submodule" &&
git reset --hard master &&
git reset --hard master >/dev/null 2>&1 &&
( cd submod && git clean -f && git reset --hard ) &&
git submodule update -N
'
Expand Down

0 comments on commit 3e8e691

Please sign in to comment.