Skip to content

Commit 386c076

Browse files
chooglengitster
authored andcommitted
fetch --negotiate-only: do not update submodules
`git fetch --negotiate-only` is an implementation detail of push negotiation and, unlike most `git fetch` invocations, does not actually update the main repository. Thus it should not update submodules even if submodule recursion is enabled. This is not just slow, it is wrong e.g. push negotiation with "submodule.recurse=true" will cause submodules to be updated because it invokes `git fetch --negotiate-only`. Fix this by disabling submodule recursion if --negotiate-only was given. Since this makes --negotiate-only and --recurse-submodules incompatible, check for this invalid combination and die. This does not use the "goto cleanup" introduced in the previous commit because we want to recurse through submodules whenever a ref is fetched, and this can happen without introducing new objects. Signed-off-by: Glen Choo <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 135a12b commit 386c076

File tree

4 files changed

+48
-1
lines changed

4 files changed

+48
-1
lines changed

Documentation/fetch-options.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ configuration variables documented in linkgit:git-config[1], and the
7171
ancestors of the provided `--negotiation-tip=*` arguments,
7272
which we have in common with the server.
7373
+
74+
This is incompatible with `--recurse-submodules=[yes|on-demand]`.
7475
Internally this is used to implement the `push.negotiate` option, see
7576
linkgit:git-config[1].
7677

builtin/fetch.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ static struct transport *gtransport;
7575
static struct transport *gsecondary;
7676
static const char *submodule_prefix = "";
7777
static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
78+
static int recurse_submodules_cli = RECURSE_SUBMODULES_DEFAULT;
7879
static int recurse_submodules_default = RECURSE_SUBMODULES_ON_DEMAND;
7980
static int shown_url = 0;
8081
static struct refspec refmap = REFSPEC_INIT_FETCH;
@@ -166,7 +167,7 @@ static struct option builtin_fetch_options[] = {
166167
N_("prune remote-tracking branches no longer on remote")),
167168
OPT_BOOL('P', "prune-tags", &prune_tags,
168169
N_("prune local tags no longer on remote and clobber changed tags")),
169-
OPT_CALLBACK_F(0, "recurse-submodules", &recurse_submodules, N_("on-demand"),
170+
OPT_CALLBACK_F(0, "recurse-submodules", &recurse_submodules_cli, N_("on-demand"),
170171
N_("control recursive fetching of submodules"),
171172
PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules),
172173
OPT_BOOL(0, "dry-run", &dry_run,
@@ -1996,6 +1997,27 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
19961997

19971998
argc = parse_options(argc, argv, prefix,
19981999
builtin_fetch_options, builtin_fetch_usage, 0);
2000+
2001+
if (recurse_submodules_cli != RECURSE_SUBMODULES_DEFAULT)
2002+
recurse_submodules = recurse_submodules_cli;
2003+
2004+
if (negotiate_only) {
2005+
switch (recurse_submodules_cli) {
2006+
case RECURSE_SUBMODULES_OFF:
2007+
case RECURSE_SUBMODULES_DEFAULT:
2008+
/*
2009+
* --negotiate-only should never recurse into
2010+
* submodules. Skip it by setting recurse_submodules to
2011+
* RECURSE_SUBMODULES_OFF.
2012+
*/
2013+
recurse_submodules = RECURSE_SUBMODULES_OFF;
2014+
break;
2015+
2016+
default:
2017+
die(_("--negotiate-only and --recurse-submodules cannot be used together"));
2018+
}
2019+
}
2020+
19992021
if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
20002022
int *sfjc = submodule_fetch_jobs_config == -1
20012023
? &submodule_fetch_jobs_config : NULL;

t/t5516-fetch-push.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,18 @@ test_expect_success 'push with negotiation proceeds anyway even if negotiation f
229229
test_i18ngrep "push negotiation failed" err
230230
'
231231

232+
test_expect_success 'push with negotiation does not attempt to fetch submodules' '
233+
mk_empty submodule_upstream &&
234+
test_commit -C submodule_upstream submodule_commit &&
235+
git submodule add ./submodule_upstream submodule &&
236+
mk_empty testrepo &&
237+
git push testrepo $the_first_commit:refs/remotes/origin/first_commit &&
238+
test_commit -C testrepo unrelated_commit &&
239+
git -C testrepo config receive.hideRefs refs/remotes/origin/first_commit &&
240+
git -c submodule.recurse=true -c protocol.version=2 -c push.negotiate=1 push testrepo refs/heads/main:refs/remotes/origin/main 2>err &&
241+
! grep "Fetching submodule" err
242+
'
243+
232244
test_expect_success 'push without wildcard' '
233245
mk_empty testrepo &&
234246

t/t5702-protocol-v2.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,18 @@ test_expect_success 'usage: --negotiate-only without --negotiation-tip' '
628628
test_cmp err.expect err.actual
629629
'
630630

631+
test_expect_success 'usage: --negotiate-only with --recurse-submodules' '
632+
cat >err.expect <<-\EOF &&
633+
fatal: --negotiate-only and --recurse-submodules cannot be used together
634+
EOF
635+
636+
test_must_fail git -c protocol.version=2 -C client fetch \
637+
--negotiate-only \
638+
--recurse-submodules \
639+
origin 2>err.actual &&
640+
test_cmp err.expect err.actual
641+
'
642+
631643
test_expect_success 'file:// --negotiate-only' '
632644
SERVER="server" &&
633645
URI="file://$(pwd)/server" &&

0 commit comments

Comments
 (0)