Skip to content

Commit e62f779

Browse files
jonathantanmyttaylorr
authored andcommitted
Doc: document push.recurseSubmodules=only
Git learned pushing submodules without pushing the superproject by the user specifying --recurse-submodules=only through 6c656c3 ("submodules: add RECURSE_SUBMODULES_ONLY value", 2016-12-20) and 225e8bf ("push: add option to push only submodules", 2016-12-20). For users who use this feature regularly, it is desirable to have an equivalent configuration. It turns out that such a configuration (push.recurseSubmodules=only) is already supported, even though it is neither documented nor mentioned in the commit messages, due to the way the --recurse-submodules=only feature was implemented (a function used to parse --recurse-submodules was updated to support "only", but that same function is used to parse push.recurseSubmodules too). What is left is to document it and test it, which is what this commit does. There is a possible point of confusion when recursing into a submodule that itself has the push.recurseSubmodules=only configuration, because if a repository has only its submodules pushed and not itself, its superproject can never be pushed. Therefore, treat such configurations as being "on-demand", and print a warning message. Signed-off-by: Jonathan Tan <[email protected]> Signed-off-by: Taylor Blau <[email protected]>
1 parent 3b08839 commit e62f779

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)