Skip to content

Commit 3e8e691

Browse files
jmahgitster
authored andcommitted
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 <[email protected]> Acked-by: David Aguilar <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2765233 commit 3e8e691

File tree

3 files changed

+72
-69
lines changed

3 files changed

+72
-69
lines changed

Documentation/git-mergetool.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ Use `git mergetool` to run one of several merge utilities to resolve
1616
merge conflicts. It is typically run after 'git merge'.
1717

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

2324
OPTIONS
2425
-------

git-mergetool.sh

Lines changed: 28 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -342,64 +342,44 @@ merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo fa
342342

343343
last_status=0
344344
rollup_status=0
345-
rerere=false
346-
347-
files_to_merge() {
348-
if test "$rerere" = true
349-
then
350-
git rerere remaining
351-
else
352-
git ls-files -u | sed -e 's/^[^ ]* //' | sort -u
353-
fi
354-
}
355-
345+
files=
356346

357347
if test $# -eq 0 ; then
358348
cd_to_toplevel
359349

360350
if test -e "$GIT_DIR/MERGE_RR"
361351
then
362-
rerere=true
352+
files=$(git rerere remaining)
353+
else
354+
files=$(git ls-files -u | sed -e 's/^[^ ]* //' | sort -u)
363355
fi
356+
else
357+
files=$(git ls-files -u -- "$@" | sed -e 's/^[^ ]* //' | sort -u)
358+
fi
364359

365-
files=$(files_to_merge)
366-
if test -z "$files" ; then
367-
echo "No files need merging"
368-
exit 0
369-
fi
360+
if test -z "$files" ; then
361+
echo "No files need merging"
362+
exit 0
363+
fi
370364

371-
# Save original stdin
372-
exec 3<&0
365+
# Save original stdin
366+
exec 3<&0
373367

374-
printf "Merging:\n"
375-
printf "$files\n"
368+
printf "Merging:\n"
369+
printf "$files\n"
376370

377-
files_to_merge |
378-
while IFS= read i
379-
do
380-
if test $last_status -ne 0; then
381-
prompt_after_failed_merge <&3 || exit 1
382-
fi
383-
printf "\n"
384-
merge_file "$i" <&3
385-
last_status=$?
386-
if test $last_status -ne 0; then
387-
rollup_status=1
388-
fi
389-
done
390-
else
391-
while test $# -gt 0; do
392-
if test $last_status -ne 0; then
393-
prompt_after_failed_merge || exit 1
394-
fi
395-
printf "\n"
396-
merge_file "$1"
397-
last_status=$?
398-
if test $last_status -ne 0; then
399-
rollup_status=1
400-
fi
401-
shift
402-
done
403-
fi
371+
IFS='
372+
'; for i in $files
373+
do
374+
if test $last_status -ne 0; then
375+
prompt_after_failed_merge <&3 || exit 1
376+
fi
377+
printf "\n"
378+
merge_file "$i" <&3
379+
last_status=$?
380+
if test $last_status -ne 0; then
381+
rollup_status=1
382+
fi
383+
done
404384

405385
exit $rollup_status

t/t7610-mergetool.sh

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Testing basic merge tool invocation'
1616
test_expect_success 'setup' '
1717
git config rerere.enabled true &&
1818
echo master >file1 &&
19+
echo master spaced >"spaced name" &&
1920
echo master file11 >file11 &&
2021
echo master file12 >file12 &&
2122
echo master file13 >file13 &&
@@ -30,13 +31,14 @@ test_expect_success 'setup' '
3031
git commit -m "Add foo"
3132
) &&
3233
git submodule add git://example.com/submod submod &&
33-
git add file1 file1[1-4] subdir/file3 .gitmodules submod &&
34+
git add file1 "spaced name" file1[1-4] subdir/file3 .gitmodules submod &&
3435
git commit -m "add initial versions" &&
3536
3637
git checkout -b branch1 master &&
3738
git submodule update -N &&
3839
echo branch1 change >file1 &&
3940
echo branch1 newfile >file2 &&
41+
echo branch1 spaced >"spaced name" &&
4042
echo branch1 change file11 >file11 &&
4143
echo branch1 change file13 >file13 &&
4244
echo branch1 sub >subdir/file3 &&
@@ -47,14 +49,15 @@ test_expect_success 'setup' '
4749
git commit -m "Add bar on branch1" &&
4850
git checkout -b submod-branch1
4951
) &&
50-
git add file1 file11 file13 file2 subdir/file3 submod &&
52+
git add file1 "spaced name" file11 file13 file2 subdir/file3 submod &&
5153
git rm file12 &&
5254
git commit -m "branch1 changes" &&
5355
5456
git checkout master &&
5557
git submodule update -N &&
5658
echo master updated >file1 &&
5759
echo master new >file2 &&
60+
echo master updated spaced >"spaced name" &&
5861
echo master updated file12 >file12 &&
5962
echo master updated file14 >file14 &&
6063
echo master new sub >subdir/file3 &&
@@ -65,7 +68,7 @@ test_expect_success 'setup' '
6568
git commit -m "Add bar on master" &&
6669
git checkout -b submod-master
6770
) &&
68-
git add file1 file12 file14 file2 subdir/file3 submod &&
71+
git add file1 "spaced name" file12 file14 file2 subdir/file3 submod &&
6972
git rm file11 &&
7073
git commit -m "master updates" &&
7174
@@ -78,8 +81,8 @@ test_expect_success 'custom mergetool' '
7881
git checkout -b test1 branch1 &&
7982
git submodule update -N &&
8083
test_must_fail git merge master >/dev/null 2>&1 &&
81-
( yes "" | git mergetool file1 >/dev/null 2>&1 ) &&
82-
( yes "" | git mergetool file2 >/dev/null 2>&1 ) &&
84+
( yes "" | git mergetool file1 file1 ) &&
85+
( yes "" | git mergetool file2 "spaced name" >/dev/null 2>&1 ) &&
8386
( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
8487
( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
8588
( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
@@ -97,6 +100,7 @@ test_expect_success 'mergetool crlf' '
97100
test_must_fail git merge master >/dev/null 2>&1 &&
98101
( yes "" | git mergetool file1 >/dev/null 2>&1 ) &&
99102
( yes "" | git mergetool file2 >/dev/null 2>&1 ) &&
103+
( yes "" | git mergetool "spaced name" >/dev/null 2>&1 ) &&
100104
( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
101105
( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
102106
( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
@@ -126,7 +130,7 @@ test_expect_success 'mergetool on file in parent dir' '
126130
(
127131
cd subdir &&
128132
( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) &&
129-
( yes "" | git mergetool ../file2 >/dev/null 2>&1 ) &&
133+
( yes "" | git mergetool ../file2 ../spaced\ name >/dev/null 2>&1 ) &&
130134
( yes "d" | git mergetool ../file11 >/dev/null 2>&1 ) &&
131135
( yes "d" | git mergetool ../file12 >/dev/null 2>&1 ) &&
132136
( yes "l" | git mergetool ../submod >/dev/null 2>&1 ) &&
@@ -180,6 +184,24 @@ test_expect_success 'mergetool skips resolved paths when rerere is active' '
180184
git reset --hard
181185
'
182186

187+
test_expect_success 'mergetool takes partial path' '
188+
git config rerere.enabled false &&
189+
git checkout -b test12 branch1 &&
190+
git submodule update -N &&
191+
test_must_fail git merge master &&
192+
193+
#shouldnt need these lines
194+
#( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
195+
#( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
196+
#( yes "l" | git mergetool submod >/dev/null 2>&1 ) &&
197+
#( yes "" | git mergetool file1 file2 >/dev/null 2>&1 ) &&
198+
199+
( yes "" | git mergetool subdir ) &&
200+
201+
test "$(cat subdir/file3)" = "master new sub" &&
202+
git reset --hard
203+
'
204+
183205
test_expect_success 'deleted vs modified submodule' '
184206
git checkout -b test6 branch1 &&
185207
git submodule update -N &&
@@ -189,7 +211,7 @@ test_expect_success 'deleted vs modified submodule' '
189211
git checkout -b test6.a test6 &&
190212
test_must_fail git merge master &&
191213
test -n "$(git ls-files -u)" &&
192-
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
214+
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
193215
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
194216
( yes "r" | git mergetool submod ) &&
195217
rmdir submod && mv submod-movedaside submod &&
@@ -205,7 +227,7 @@ test_expect_success 'deleted vs modified submodule' '
205227
git submodule update -N &&
206228
test_must_fail git merge master &&
207229
test -n "$(git ls-files -u)" &&
208-
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
230+
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
209231
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
210232
( yes "l" | git mergetool submod ) &&
211233
test ! -e submod &&
@@ -218,7 +240,7 @@ test_expect_success 'deleted vs modified submodule' '
218240
git submodule update -N &&
219241
test_must_fail git merge test6 &&
220242
test -n "$(git ls-files -u)" &&
221-
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
243+
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
222244
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
223245
( yes "r" | git mergetool submod ) &&
224246
test ! -e submod &&
@@ -233,7 +255,7 @@ test_expect_success 'deleted vs modified submodule' '
233255
git submodule update -N &&
234256
test_must_fail git merge test6 &&
235257
test -n "$(git ls-files -u)" &&
236-
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
258+
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
237259
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
238260
( yes "l" | git mergetool submod ) &&
239261
test "$(cat submod/bar)" = "master submodule" &&
@@ -256,7 +278,7 @@ test_expect_success 'file vs modified submodule' '
256278
git checkout -b test7.a branch1 &&
257279
test_must_fail git merge master &&
258280
test -n "$(git ls-files -u)" &&
259-
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
281+
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
260282
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
261283
( yes "r" | git mergetool submod ) &&
262284
rmdir submod && mv submod-movedaside submod &&
@@ -271,7 +293,7 @@ test_expect_success 'file vs modified submodule' '
271293
git checkout -b test7.b test7 &&
272294
test_must_fail git merge master &&
273295
test -n "$(git ls-files -u)" &&
274-
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
296+
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
275297
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
276298
( yes "l" | git mergetool submod ) &&
277299
git submodule update -N &&
@@ -286,7 +308,7 @@ test_expect_success 'file vs modified submodule' '
286308
git submodule update -N &&
287309
test_must_fail git merge test7 &&
288310
test -n "$(git ls-files -u)" &&
289-
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
311+
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
290312
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
291313
( yes "r" | git mergetool submod ) &&
292314
test -d submod.orig &&
@@ -301,7 +323,7 @@ test_expect_success 'file vs modified submodule' '
301323
git submodule update -N &&
302324
test_must_fail git merge test7 &&
303325
test -n "$(git ls-files -u)" &&
304-
( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
326+
( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
305327
( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
306328
( yes "l" | git mergetool submod ) &&
307329
test "$(cat submod/bar)" = "master submodule" &&
@@ -388,7 +410,7 @@ test_expect_success 'directory vs modified submodule' '
388410
test "$(cat submod/file16)" = "not a submodule" &&
389411
rm -rf submod.orig &&
390412
391-
git reset --hard &&
413+
git reset --hard >/dev/null 2>&1 &&
392414
test_must_fail git merge master &&
393415
test -n "$(git ls-files -u)" &&
394416
test ! -e submod.orig &&
@@ -400,7 +422,7 @@ test_expect_success 'directory vs modified submodule' '
400422
( cd submod && git clean -f && git reset --hard ) &&
401423
git submodule update -N &&
402424
test "$(cat submod/bar)" = "master submodule" &&
403-
git reset --hard && rm -rf submod-movedaside &&
425+
git reset --hard >/dev/null 2>&1 && rm -rf submod-movedaside &&
404426
405427
git checkout -b test11.c master &&
406428
git submodule update -N &&
@@ -410,15 +432,15 @@ test_expect_success 'directory vs modified submodule' '
410432
git submodule update -N &&
411433
test "$(cat submod/bar)" = "master submodule" &&
412434
413-
git reset --hard &&
435+
git reset --hard >/dev/null 2>&1 &&
414436
git submodule update -N &&
415437
test_must_fail git merge test11 &&
416438
test -n "$(git ls-files -u)" &&
417439
test ! -e submod.orig &&
418440
( yes "r" | git mergetool submod ) &&
419441
test "$(cat submod/file16)" = "not a submodule" &&
420442
421-
git reset --hard master &&
443+
git reset --hard master >/dev/null 2>&1 &&
422444
( cd submod && git clean -f && git reset --hard ) &&
423445
git submodule update -N
424446
'

0 commit comments

Comments
 (0)