Skip to content

Commit 173fc54

Browse files
committed
Merge branch 'jt/submodule-on-demand'
Push all submodules recursively with '--recurse-submodules=on-demand'. * jt/submodule-on-demand: Doc: document push.recurseSubmodules=only
2 parents 8d7b35b + e62f779 commit 173fc54

File tree

5 files changed

+73
-15
lines changed

5 files changed

+73
-15
lines changed

Documentation/config/push.txt

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -110,18 +110,8 @@ This will result in only b (a and c are cleared).
110110
----
111111

112112
push.recurseSubmodules::
113-
Make sure all submodule commits used by the revisions to be pushed
114-
are available on a remote-tracking branch. If the value is 'check'
115-
then Git will verify that all submodule commits that changed in the
116-
revisions to be pushed are available on at least one remote of the
117-
submodule. If any commits are missing, the push will be aborted and
118-
exit with non-zero status. If the value is 'on-demand' then all
119-
submodules that changed in the revisions to be pushed will be
120-
pushed. If on-demand was not able to push all necessary revisions
121-
it will also be aborted and exit with non-zero status. If the value
122-
is 'no' then default behavior of ignoring submodules when pushing
123-
is retained. You may override this configuration at time of push by
124-
specifying '--recurse-submodules=check|on-demand|no'.
113+
May be "check", "on-demand", "only", or "no", with the same behavior
114+
as that of "push --recurse-submodules".
125115
If not set, 'no' is used by default, unless 'submodule.recurse' is
126116
set (in which case a 'true' value means 'on-demand').
127117

Documentation/git-push.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,10 +409,14 @@ Specifying `--no-force-if-includes` disables this behavior.
409409
all submodules that changed in the revisions to be pushed will be
410410
pushed. If on-demand was not able to push all necessary revisions it will
411411
also be aborted and exit with non-zero status. If 'only' is used all
412-
submodules will be recursively pushed while the superproject is left
412+
submodules will be pushed while the superproject is left
413413
unpushed. A value of 'no' or using `--no-recurse-submodules` can be used
414414
to override the push.recurseSubmodules configuration variable when no
415415
submodule recursion is required.
416+
+
417+
When using 'on-demand' or 'only', if a submodule has a
418+
"push.recurseSubmodules={on-demand,only}" or "submodule.recurse" configuration,
419+
further recursion will occur. In this case, "only" is treated as "on-demand".
416420

417421
--[no-]verify::
418422
Toggle the pre-push hook (see linkgit:githooks[5]). The

builtin/push.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,8 +466,16 @@ static int option_parse_recurse_submodules(const struct option *opt,
466466

467467
if (unset)
468468
*recurse_submodules = RECURSE_SUBMODULES_OFF;
469-
else
470-
*recurse_submodules = parse_push_recurse_submodules_arg(opt->long_name, arg);
469+
else {
470+
if (!strcmp(arg, "only-is-on-demand")) {
471+
if (*recurse_submodules == RECURSE_SUBMODULES_ONLY) {
472+
warning(_("recursing into submodule with push.recurseSubmodules=only; using on-demand instead"));
473+
*recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND;
474+
}
475+
} else {
476+
*recurse_submodules = parse_push_recurse_submodules_arg(opt->long_name, arg);
477+
}
478+
}
471479

472480
return 0;
473481
}

submodule.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,12 @@ static int push_submodule(const char *path,
11301130
if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) {
11311131
struct child_process cp = CHILD_PROCESS_INIT;
11321132
strvec_push(&cp.args, "push");
1133+
/*
1134+
* When recursing into a submodule, treat any "only" configurations as "on-
1135+
* demand", since "only" would not work (we need all submodules to be pushed
1136+
* in order to be able to push the superproject).
1137+
*/
1138+
strvec_push(&cp.args, "--recurse-submodules=only-is-on-demand");
11331139
if (dry_run)
11341140
strvec_push(&cp.args, "--dry-run");
11351141

t/t5531-deep-submodule-push.sh

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,56 @@ test_expect_success 'push only unpushed submodules recursively' '
512512
test_cmp expected_pub actual_pub
513513
'
514514

515+
setup_subsub () {
516+
git init upstream &&
517+
git init upstream/sub &&
518+
git init upstream/sub/deepsub &&
519+
test_commit -C upstream/sub/deepsub innermost &&
520+
git -C upstream/sub submodule add ./deepsub deepsub &&
521+
git -C upstream/sub commit -m middle &&
522+
git -C upstream submodule add ./sub sub &&
523+
git -C upstream commit -m outermost &&
524+
525+
git -c protocol.file.allow=always clone --recurse-submodules upstream downstream &&
526+
git -C downstream/sub/deepsub checkout -b downstream-branch &&
527+
git -C downstream/sub checkout -b downstream-branch &&
528+
git -C downstream checkout -b downstream-branch
529+
}
530+
531+
new_downstream_commits () {
532+
test_commit -C downstream/sub/deepsub new-innermost &&
533+
git -C downstream/sub add deepsub &&
534+
git -C downstream/sub commit -m new-middle &&
535+
git -C downstream add sub &&
536+
git -C downstream commit -m new-outermost
537+
}
538+
539+
test_expect_success 'push with push.recurseSubmodules=only on superproject' '
540+
test_when_finished rm -rf upstream downstream &&
541+
setup_subsub &&
542+
new_downstream_commits &&
543+
git -C downstream config push.recurseSubmodules only &&
544+
git -C downstream push origin downstream-branch &&
545+
546+
test_must_fail git -C upstream rev-parse refs/heads/downstream-branch &&
547+
git -C upstream/sub rev-parse refs/heads/downstream-branch &&
548+
test_must_fail git -C upstream/sub/deepsub rev-parse refs/heads/downstream-branch
549+
'
550+
551+
test_expect_success 'push with push.recurseSubmodules=only on superproject and top-level submodule' '
552+
test_when_finished rm -rf upstream downstream &&
553+
setup_subsub &&
554+
new_downstream_commits &&
555+
git -C downstream config push.recurseSubmodules only &&
556+
git -C downstream/sub config push.recurseSubmodules only &&
557+
git -C downstream push origin downstream-branch 2> err &&
558+
559+
test_must_fail git -C upstream rev-parse refs/heads/downstream-branch &&
560+
git -C upstream/sub rev-parse refs/heads/downstream-branch &&
561+
git -C upstream/sub/deepsub rev-parse refs/heads/downstream-branch &&
562+
grep "recursing into submodule with push.recurseSubmodules=only; using on-demand instead" err
563+
'
564+
515565
test_expect_success 'push propagating the remotes name to a submodule' '
516566
git -C work remote add origin ../pub.git &&
517567
git -C work remote add pub ../pub.git &&

0 commit comments

Comments
 (0)