Skip to content

Commit 15ffb7c

Browse files
iveqygitster
authored andcommitted
submodule update: continue when a checkout fails
"git submodule update" stops at the first error and gives control back to the user. Only after the user fixes the problematic submodule and runs "git submodule update" again, the second error is found. And the user needs to repeat until all the problems are found and fixed one by one. This is tedious. Instead, the command can remember which submodules it had trouble with, continue updating the ones it can, and report which ones had errors at the end. The user can run "git submodule update", find all the ones that need minor fixing (e.g. working tree was dirty) to fix them in a single pass. Then another "git submodule update" can be run to update all. Note that the problematic submodules are skipped only when they are to be integrated with a safer value of submodule.<name>.update option, namely "checkout". Fixing a failure in a submodule that uses "rebase" or "merge" may need an involved conflict resolution by the user, and leaving too many submodules in states that need resolution would not reduce the mental burden on the user. Signed-off-by: Fredrik Gustafsson <[email protected]> Mentored-by: Jens Lehmann <[email protected]> Mentored-by: Heiko Voigt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent adb231c commit 15ffb7c

File tree

2 files changed

+188
-6
lines changed

2 files changed

+188
-6
lines changed

git-submodule.sh

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,8 @@ cmd_update()
444444
fi
445445

446446
cloned_modules=
447-
module_list "$@" |
447+
module_list "$@" | {
448+
err=
448449
while read mode sha1 stage path
449450
do
450451
if test "$stage" = U
@@ -525,17 +526,54 @@ cmd_update()
525526
;;
526527
esac
527528

528-
(clear_local_git_env; cd "$path" && $command "$sha1") ||
529-
die "Unable to $action '$sha1' in submodule path '$path'"
530-
say "Submodule path '$path': $msg '$sha1'"
529+
if (clear_local_git_env; cd "$path" && $command "$sha1")
530+
then
531+
say "Submodule path '$path': $msg '$sha1'"
532+
else
533+
case $action in
534+
rebase|merge)
535+
die_with_status 2 "Unable to $action '$sha1' in submodule path '$path'"
536+
;;
537+
*)
538+
err="${err};Failed to $action in submodule path '$path'"
539+
continue
540+
;;
541+
esac
542+
fi
531543
fi
532544

533545
if test -n "$recursive"
534546
then
535-
(clear_local_git_env; cd "$path" && eval cmd_update "$orig_flags") ||
536-
die "Failed to recurse into submodule path '$path'"
547+
(clear_local_git_env; cd "$path" && eval cmd_update "$orig_flags")
548+
res=$?
549+
if test $res -gt 0
550+
then
551+
if test $res -eq 1
552+
then
553+
err="${err};Failed to recurse into submodule path '$path'"
554+
continue
555+
else
556+
die_with_status $res "Failed to recurse into submodule path '$path'"
557+
fi
558+
fi
537559
fi
538560
done
561+
562+
if test -n "$err"
563+
then
564+
OIFS=$IFS
565+
IFS=';'
566+
for e in $err
567+
do
568+
if test -n "$e"
569+
then
570+
echo >&2 "$e"
571+
fi
572+
done
573+
IFS=$OIFS
574+
exit 1
575+
fi
576+
}
539577
}
540578

541579
set_name_rev () {

t/t7406-submodule-update.sh

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,4 +298,148 @@ test_expect_success 'submodule update ignores update=rebase config for new submo
298298
)
299299
'
300300

301+
test_expect_success 'submodule update continues after checkout error' '
302+
(cd super &&
303+
git reset --hard HEAD &&
304+
git submodule add ../submodule submodule2 &&
305+
git submodule init &&
306+
git commit -am "new_submodule" &&
307+
(cd submodule2 &&
308+
git rev-parse --max-count=1 HEAD > ../expect
309+
) &&
310+
(cd submodule &&
311+
test_commit "update_submodule" file
312+
) &&
313+
(cd submodule2 &&
314+
test_commit "update_submodule2" file
315+
) &&
316+
git add submodule &&
317+
git add submodule2 &&
318+
git commit -m "two_new_submodule_commits" &&
319+
(cd submodule &&
320+
echo "" > file
321+
) &&
322+
git checkout HEAD^ &&
323+
test_must_fail git submodule update &&
324+
(cd submodule2 &&
325+
git rev-parse --max-count=1 HEAD > ../actual
326+
) &&
327+
test_cmp expect actual
328+
)
329+
'
330+
test_expect_success 'submodule update continues after recursive checkout error' '
331+
(cd super &&
332+
git reset --hard HEAD &&
333+
git checkout master &&
334+
git submodule update &&
335+
(cd submodule &&
336+
git submodule add ../submodule subsubmodule &&
337+
git submodule init &&
338+
git commit -m "new_subsubmodule"
339+
) &&
340+
git add submodule &&
341+
git commit -m "update_submodule" &&
342+
(cd submodule &&
343+
(cd subsubmodule &&
344+
test_commit "update_subsubmodule" file
345+
) &&
346+
git add subsubmodule &&
347+
test_commit "update_submodule_again" file &&
348+
(cd subsubmodule &&
349+
test_commit "update_subsubmodule_again" file
350+
) &&
351+
test_commit "update_submodule_again_again" file
352+
) &&
353+
(cd submodule2 &&
354+
git rev-parse --max-count=1 HEAD > ../expect &&
355+
test_commit "update_submodule2_again" file
356+
) &&
357+
git add submodule &&
358+
git add submodule2 &&
359+
git commit -m "new_commits" &&
360+
git checkout HEAD^ &&
361+
(cd submodule &&
362+
git checkout HEAD^ &&
363+
(cd subsubmodule &&
364+
echo "" > file
365+
)
366+
) &&
367+
test_must_fail git submodule update --recursive &&
368+
(cd submodule2 &&
369+
git rev-parse --max-count=1 HEAD > ../actual
370+
) &&
371+
test_cmp expect actual
372+
)
373+
'
374+
375+
test_expect_success 'submodule update exit immediately in case of merge conflict' '
376+
(cd super &&
377+
git checkout master &&
378+
git reset --hard HEAD &&
379+
(cd submodule &&
380+
(cd subsubmodule &&
381+
git reset --hard HEAD
382+
)
383+
) &&
384+
git submodule update --recursive &&
385+
(cd submodule &&
386+
test_commit "update_submodule_2" file
387+
) &&
388+
(cd submodule2 &&
389+
test_commit "update_submodule2_2" file
390+
) &&
391+
git add submodule &&
392+
git add submodule2 &&
393+
git commit -m "two_new_submodule_commits" &&
394+
(cd submodule &&
395+
git checkout master &&
396+
test_commit "conflict" file &&
397+
echo "conflict" > file
398+
) &&
399+
git checkout HEAD^ &&
400+
(cd submodule2 &&
401+
git rev-parse --max-count=1 HEAD > ../expect
402+
) &&
403+
git config submodule.submodule.update merge &&
404+
test_must_fail git submodule update &&
405+
(cd submodule2 &&
406+
git rev-parse --max-count=1 HEAD > ../actual
407+
) &&
408+
test_cmp expect actual
409+
)
410+
'
411+
test_expect_success 'submodule update exit immediately after recursive rebase error' '
412+
(cd super &&
413+
git checkout master &&
414+
git reset --hard HEAD &&
415+
(cd submodule &&
416+
git reset --hard HEAD &&
417+
git submodule update --recursive
418+
) &&
419+
(cd submodule &&
420+
test_commit "update_submodule_3" file
421+
) &&
422+
(cd submodule2 &&
423+
test_commit "update_submodule2_3" file
424+
) &&
425+
git add submodule &&
426+
git add submodule2 &&
427+
git commit -m "two_new_submodule_commits" &&
428+
(cd submodule &&
429+
git checkout master &&
430+
test_commit "conflict2" file &&
431+
echo "conflict" > file
432+
) &&
433+
git checkout HEAD^ &&
434+
(cd submodule2 &&
435+
git rev-parse --max-count=1 HEAD > ../expect
436+
) &&
437+
git config submodule.submodule.update rebase &&
438+
test_must_fail git submodule update &&
439+
(cd submodule2 &&
440+
git rev-parse --max-count=1 HEAD > ../actual
441+
) &&
442+
test_cmp expect actual
443+
)
444+
'
301445
test_done

0 commit comments

Comments
 (0)