mergetool: Use args as pathspec to unmerged files

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>
This commit is contained in:
Jonathon Mah 2011-09-15 19:12:10 -07:00 committed by Junio C Hamano
parent 2765233c64
commit 3e8e691abe
3 changed files with 74 additions and 71 deletions

View File

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

View File

@ -342,64 +342,44 @@ merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo fa
last_status=0 last_status=0
rollup_status=0 rollup_status=0
rerere=false files=
files_to_merge() {
if test "$rerere" = true
then
git rerere remaining
else
git ls-files -u | sed -e 's/^[^ ]* //' | sort -u
fi
}
if test $# -eq 0 ; then if test $# -eq 0 ; then
cd_to_toplevel cd_to_toplevel
if test -e "$GIT_DIR/MERGE_RR" if test -e "$GIT_DIR/MERGE_RR"
then then
rerere=true files=$(git rerere remaining)
else
files=$(git ls-files -u | sed -e 's/^[^ ]* //' | sort -u)
fi fi
files=$(files_to_merge)
if test -z "$files" ; then
echo "No files need merging"
exit 0
fi
# Save original stdin
exec 3<&0
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 else
while test $# -gt 0; do files=$(git ls-files -u -- "$@" | sed -e 's/^[^ ]* //' | sort -u)
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 fi
if test -z "$files" ; then
echo "No files need merging"
exit 0
fi
# Save original stdin
exec 3<&0
printf "Merging:\n"
printf "$files\n"
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 exit $rollup_status

View File

@ -16,6 +16,7 @@ Testing basic merge tool invocation'
test_expect_success 'setup' ' test_expect_success 'setup' '
git config rerere.enabled true && git config rerere.enabled true &&
echo master >file1 && echo master >file1 &&
echo master spaced >"spaced name" &&
echo master file11 >file11 && echo master file11 >file11 &&
echo master file12 >file12 && echo master file12 >file12 &&
echo master file13 >file13 && echo master file13 >file13 &&
@ -30,13 +31,14 @@ test_expect_success 'setup' '
git commit -m "Add foo" git commit -m "Add foo"
) && ) &&
git submodule add git://example.com/submod submod && 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 commit -m "add initial versions" &&
git checkout -b branch1 master && git checkout -b branch1 master &&
git submodule update -N && git submodule update -N &&
echo branch1 change >file1 && echo branch1 change >file1 &&
echo branch1 newfile >file2 && echo branch1 newfile >file2 &&
echo branch1 spaced >"spaced name" &&
echo branch1 change file11 >file11 && echo branch1 change file11 >file11 &&
echo branch1 change file13 >file13 && echo branch1 change file13 >file13 &&
echo branch1 sub >subdir/file3 && echo branch1 sub >subdir/file3 &&
@ -47,7 +49,7 @@ test_expect_success 'setup' '
git commit -m "Add bar on branch1" && git commit -m "Add bar on branch1" &&
git checkout -b submod-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 rm file12 &&
git commit -m "branch1 changes" && git commit -m "branch1 changes" &&
@ -55,6 +57,7 @@ test_expect_success 'setup' '
git submodule update -N && git submodule update -N &&
echo master updated >file1 && echo master updated >file1 &&
echo master new >file2 && echo master new >file2 &&
echo master updated spaced >"spaced name" &&
echo master updated file12 >file12 && echo master updated file12 >file12 &&
echo master updated file14 >file14 && echo master updated file14 >file14 &&
echo master new sub >subdir/file3 && echo master new sub >subdir/file3 &&
@ -65,7 +68,7 @@ test_expect_success 'setup' '
git commit -m "Add bar on master" && git commit -m "Add bar on master" &&
git checkout -b submod-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 rm file11 &&
git commit -m "master updates" && git commit -m "master updates" &&
@ -78,8 +81,8 @@ test_expect_success 'custom mergetool' '
git checkout -b test1 branch1 && git checkout -b test1 branch1 &&
git submodule update -N && git submodule update -N &&
test_must_fail git merge master >/dev/null 2>&1 && test_must_fail git merge master >/dev/null 2>&1 &&
( yes "" | git mergetool file1 >/dev/null 2>&1 ) && ( yes "" | git mergetool file1 file1 ) &&
( yes "" | git mergetool file2 >/dev/null 2>&1 ) && ( yes "" | git mergetool file2 "spaced name" >/dev/null 2>&1 ) &&
( yes "" | git mergetool subdir/file3 >/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 file11 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file12 >/dev/null 2>&1 ) && ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
@ -97,6 +100,7 @@ test_expect_success 'mergetool crlf' '
test_must_fail git merge master >/dev/null 2>&1 && test_must_fail git merge master >/dev/null 2>&1 &&
( yes "" | git mergetool file1 >/dev/null 2>&1 ) && ( yes "" | git mergetool file1 >/dev/null 2>&1 ) &&
( yes "" | git mergetool file2 >/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 "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file11 >/dev/null 2>&1 ) && ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool file12 >/dev/null 2>&1 ) && ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
@ -126,7 +130,7 @@ test_expect_success 'mergetool on file in parent dir' '
( (
cd subdir && cd subdir &&
( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) && ( 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 ../file11 >/dev/null 2>&1 ) &&
( yes "d" | git mergetool ../file12 >/dev/null 2>&1 ) && ( yes "d" | git mergetool ../file12 >/dev/null 2>&1 ) &&
( yes "l" | git mergetool ../submod >/dev/null 2>&1 ) && ( yes "l" | git mergetool ../submod >/dev/null 2>&1 ) &&
@ -180,6 +184,24 @@ test_expect_success 'mergetool skips resolved paths when rerere is active' '
git reset --hard 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' ' test_expect_success 'deleted vs modified submodule' '
git checkout -b test6 branch1 && git checkout -b test6 branch1 &&
git submodule update -N && git submodule update -N &&
@ -189,7 +211,7 @@ test_expect_success 'deleted vs modified submodule' '
git checkout -b test6.a test6 && git checkout -b test6.a test6 &&
test_must_fail git merge master && test_must_fail git merge master &&
test -n "$(git ls-files -u)" && 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 "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "r" | git mergetool submod ) && ( yes "r" | git mergetool submod ) &&
rmdir submod && mv submod-movedaside submod && rmdir submod && mv submod-movedaside submod &&
@ -205,7 +227,7 @@ test_expect_success 'deleted vs modified submodule' '
git submodule update -N && git submodule update -N &&
test_must_fail git merge master && test_must_fail git merge master &&
test -n "$(git ls-files -u)" && 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 "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "l" | git mergetool submod ) && ( yes "l" | git mergetool submod ) &&
test ! -e submod && test ! -e submod &&
@ -218,7 +240,7 @@ test_expect_success 'deleted vs modified submodule' '
git submodule update -N && git submodule update -N &&
test_must_fail git merge test6 && test_must_fail git merge test6 &&
test -n "$(git ls-files -u)" && 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 "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "r" | git mergetool submod ) && ( yes "r" | git mergetool submod ) &&
test ! -e submod && test ! -e submod &&
@ -233,7 +255,7 @@ test_expect_success 'deleted vs modified submodule' '
git submodule update -N && git submodule update -N &&
test_must_fail git merge test6 && test_must_fail git merge test6 &&
test -n "$(git ls-files -u)" && 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 "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "l" | git mergetool submod ) && ( yes "l" | git mergetool submod ) &&
test "$(cat submod/bar)" = "master submodule" && test "$(cat submod/bar)" = "master submodule" &&
@ -256,7 +278,7 @@ test_expect_success 'file vs modified submodule' '
git checkout -b test7.a branch1 && git checkout -b test7.a branch1 &&
test_must_fail git merge master && test_must_fail git merge master &&
test -n "$(git ls-files -u)" && 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 "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "r" | git mergetool submod ) && ( yes "r" | git mergetool submod ) &&
rmdir submod && mv submod-movedaside submod && rmdir submod && mv submod-movedaside submod &&
@ -271,7 +293,7 @@ test_expect_success 'file vs modified submodule' '
git checkout -b test7.b test7 && git checkout -b test7.b test7 &&
test_must_fail git merge master && test_must_fail git merge master &&
test -n "$(git ls-files -u)" && 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 "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "l" | git mergetool submod ) && ( yes "l" | git mergetool submod ) &&
git submodule update -N && git submodule update -N &&
@ -286,7 +308,7 @@ test_expect_success 'file vs modified submodule' '
git submodule update -N && git submodule update -N &&
test_must_fail git merge test7 && test_must_fail git merge test7 &&
test -n "$(git ls-files -u)" && 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 "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "r" | git mergetool submod ) && ( yes "r" | git mergetool submod ) &&
test -d submod.orig && test -d submod.orig &&
@ -301,7 +323,7 @@ test_expect_success 'file vs modified submodule' '
git submodule update -N && git submodule update -N &&
test_must_fail git merge test7 && test_must_fail git merge test7 &&
test -n "$(git ls-files -u)" && 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 "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
( yes "l" | git mergetool submod ) && ( yes "l" | git mergetool submod ) &&
test "$(cat submod/bar)" = "master submodule" && test "$(cat submod/bar)" = "master submodule" &&
@ -388,7 +410,7 @@ test_expect_success 'directory vs modified submodule' '
test "$(cat submod/file16)" = "not a submodule" && test "$(cat submod/file16)" = "not a submodule" &&
rm -rf submod.orig && rm -rf submod.orig &&
git reset --hard && git reset --hard >/dev/null 2>&1 &&
test_must_fail git merge master && test_must_fail git merge master &&
test -n "$(git ls-files -u)" && test -n "$(git ls-files -u)" &&
test ! -e submod.orig && test ! -e submod.orig &&
@ -400,7 +422,7 @@ test_expect_success 'directory vs modified submodule' '
( cd submod && git clean -f && git reset --hard ) && ( cd submod && git clean -f && git reset --hard ) &&
git submodule update -N && git submodule update -N &&
test "$(cat submod/bar)" = "master submodule" && 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 checkout -b test11.c master &&
git submodule update -N && git submodule update -N &&
@ -410,7 +432,7 @@ test_expect_success 'directory vs modified submodule' '
git submodule update -N && git submodule update -N &&
test "$(cat submod/bar)" = "master submodule" && test "$(cat submod/bar)" = "master submodule" &&
git reset --hard && git reset --hard >/dev/null 2>&1 &&
git submodule update -N && git submodule update -N &&
test_must_fail git merge test11 && test_must_fail git merge test11 &&
test -n "$(git ls-files -u)" && test -n "$(git ls-files -u)" &&
@ -418,7 +440,7 @@ test_expect_success 'directory vs modified submodule' '
( yes "r" | git mergetool submod ) && ( yes "r" | git mergetool submod ) &&
test "$(cat submod/file16)" = "not a submodule" && 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 ) && ( cd submod && git clean -f && git reset --hard ) &&
git submodule update -N git submodule update -N
' '