All of lore.kernel.org
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: Paulius Zaleckas <paulius.zaleckas@gmail.com>
Cc: git@vger.kernel.org, "Glen Choo" <glencbz@gmail.com>,
	"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
	"Patrick Steinhardt" <ps@pks.im>
Subject: Re: [PATCH v3 2/2] fetch: add fetch.submoduleErrors to make submodule fetch errors non-fatal
Date: Fri, 10 Jul 2026 15:21:02 -0700	[thread overview]
Message-ID: <xmqqmrvybi5t.fsf@gitster.g> (raw)
In-Reply-To: <20260710122655.3066377-3-paulius.zaleckas@gmail.com> (Paulius Zaleckas's message of "Fri, 10 Jul 2026 15:26:53 +0300")

Paulius Zaleckas <paulius.zaleckas@gmail.com> writes:

> When fetching with --recurse-submodules, a submodule commit that is not
> yet reachable from any of the submodule's remote refs causes the entire
> fetch to fail.  This is overly strict when the missing commit belongs to
> an upstream branch that is still being prepared (e.g. an in-progress
> merge topic): the local branch does not need that commit, so there is no
> reason to treat its absence as fatal.
>
> Add a new config key fetch.submoduleErrors (values: fail/warn) and a
> corresponding --submodule-errors=(fail|warn) command-line option that
> control this behaviour.  The default remains fail (existing behaviour);
> setting the value to warn causes submodule fetch failures to be reported
> on stderr without affecting the overall exit status of git fetch / git
> pull.
>
> Forward the option to child fetches in add_options_to_argv() so that it
> also takes effect for `git fetch --all` / `--multiple` (where per-remote
> child processes handle the submodule recursion themselves) and for
> nested submodule recursion.
>
> Signed-off-by: Paulius Zaleckas <paulius.zaleckas@gmail.com>
> ---
>  Documentation/config/fetch.adoc  | 14 ++++++
>  Documentation/fetch-options.adoc |  8 ++++
>  builtin/fetch.c                  | 41 ++++++++++++++++-
>  submodule.c                      |  8 +++-
>  submodule.h                      |  7 ++-
>  t/t5526-fetch-submodules.sh      | 76 ++++++++++++++++++++++++++++++++
>  6 files changed, 150 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/config/fetch.adoc b/Documentation/config/fetch.adoc
> index 04ac90912d..5c9c942a70 100644
> --- a/Documentation/config/fetch.adoc
> +++ b/Documentation/config/fetch.adoc
> @@ -10,6 +10,20 @@
>  	reference.
>  	Defaults to `on-demand`, or to the value of `submodule.recurse` if set.
>  
> +`fetch.submoduleErrors`::
> +	Controls how errors from submodule fetches are handled when
> +	`--recurse-submodules` is in effect. When set to `fail` (the default),
> +	any submodule fetch error causes the overall `git fetch` or `git pull`
> +	to exit with a non-zero status. When set to `warn`, submodule fetch
> +	errors are reported to standard error but do not affect the exit
> +	status of the command. This is useful when working in repositories
> +	where some branches reference submodule commits that are not yet
> +	available on the submodule remote, but those commits are not needed
> +	for the currently checked-out branch.
> ++
> +The value of this option can be overridden by the `--submodule-errors`
> +option of linkgit:git-fetch[1].
> +
>  `fetch.fsckObjects`::
>  	If it is set to true, git-fetch-pack will check all fetched
>  	objects. See `transfer.fsckObjects` for what's
> diff --git a/Documentation/fetch-options.adoc b/Documentation/fetch-options.adoc
> index 035f780e58..78525f6848 100644
> --- a/Documentation/fetch-options.adoc
> +++ b/Documentation/fetch-options.adoc
> @@ -294,6 +294,14 @@ ifndef::git-pull[]
>  `--no-recurse-submodules`::
>  	Disable recursive fetching of submodules (this has the same effect as
>  	using the `--recurse-submodules=no` option).
> +
> +`--submodule-errors=(fail|warn)`::
> +	Control how errors from submodule fetches are handled when
> +	`--recurse-submodules` is in effect. When set to `fail` (the default),
> +	any submodule fetch error causes the overall `git fetch` to exit with a
> +	non-zero status. When set to `warn`, submodule fetch errors are reported
> +	to standard error but do not affect the exit status of the command. Can
> +	also be configured via `fetch.submoduleErrors`. See linkgit:git-config[1].
>  endif::git-pull[]
>  
>  `--set-upstream`::
> diff --git a/builtin/fetch.c b/builtin/fetch.c
> index c1d7c672f4..40daaf5cc7 100644
> --- a/builtin/fetch.c
> +++ b/builtin/fetch.c
> @@ -110,6 +110,7 @@ struct fetch_config {
>  	int recurse_submodules;
>  	int parallel;
>  	int submodule_fetch_jobs;
> +	int submodule_errors;
>  };
>  
>  static int git_fetch_config(const char *k, const char *v,
> @@ -152,6 +153,19 @@ static int git_fetch_config(const char *k, const char *v,
>  		return 0;
>  	}
>  
> +	if (!strcmp(k, "fetch.submoduleerrors")) {
> +		if (!v)
> +			return config_error_nonbool(k);
> +		else if (!strcasecmp(v, "fail"))
> +			fetch_config->submodule_errors = SUBMODULE_ERRORS_FAIL;
> +		else if (!strcasecmp(v, "warn"))
> +			fetch_config->submodule_errors = SUBMODULE_ERRORS_WARN;
> +		else
> +			die(_("invalid value for '%s': '%s'"),
> +			    "fetch.submoduleErrors", v);
> +		return 0;
> +	}
> +
>  	if (!strcmp(k, "fetch.parallel")) {
>  		fetch_config->parallel = git_config_int(k, v, ctx->kvi);
>  		if (fetch_config->parallel < 0)


> @@ -2205,6 +2219,8 @@ static void add_options_to_argv(struct strvec *argv,
>  		strvec_push(argv, "--no-recurse-submodules");
>  	else if (config->recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)
>  		strvec_push(argv, "--recurse-submodules=on-demand");
> +	if (config->submodule_errors == SUBMODULE_ERRORS_WARN)
> +		strvec_push(argv, "--submodule-errors=warn");
>  	if (tags == TAGS_SET)
>  		strvec_push(argv, "--tags");
>  	else if (tags == TAGS_UNSET)

If (config->submodule_errors != SUBMODULE_ERRORS_WARN), then the argv[]
would not see any --submodule-errors=<anything> to propagate down.
Specifically, this function is called when recurse-submodules is not
disabled, and prepares argv[] used to call fetch_submodules().

>  int cmd_fetch(int argc,
>  	      const char **argv,
>  	      const char *prefix,
> @@ -2477,6 +2506,7 @@ int cmd_fetch(int argc,
>  		.recurse_submodules = RECURSE_SUBMODULES_DEFAULT,
>  		.parallel = 1,
>  		.submodule_fetch_jobs = -1,
> +		.submodule_errors = SUBMODULE_ERRORS_FAIL,
>  	};

Here, .submodule_errors member is initialized to
SUBMODULE_ERRORS_FAIL (i.e. 0).

> @@ -2491,6 +2521,7 @@ int cmd_fetch(int argc,
>  	int max_jobs = -1;
>  	int recurse_submodules_cli = RECURSE_SUBMODULES_DEFAULT;
>  	int recurse_submodules_default = RECURSE_SUBMODULES_ON_DEMAND;
> +	int submodule_errors_cli = -1; /* -1: not set on command line */
>  	int fetch_write_commit_graph = -1;
>  	int stdin_refspecs = 0;
>  	int negotiate_only = 0;
> @@ -2527,6 +2558,10 @@ int cmd_fetch(int argc,
>  		OPT_CALLBACK_F(0, "recurse-submodules", &recurse_submodules_cli, N_("on-demand"),
>  			    N_("control recursive fetching of submodules"),
>  			    PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules),
> +		OPT_CALLBACK_F(0, "submodule-errors", &submodule_errors_cli,
> +			    N_("(fail|warn)"),
> +			    N_("control how submodule fetch errors are handled"),
> +			    0, option_parse_submodule_errors),

And command line option "--submodule-errors={warn,fail}" may update
the local variable submodule_errors_cli (initialied to -1) to one of
SUBMODULE_ERRORS_{WARN,FAIL}.   These are different from -1, so we
can reliably tell if we saw a command line override, which is good.

>  		OPT_BOOL(0, "dry-run", &dry_run,
>  			 N_("dry run")),
>  		OPT_BOOL(0, "porcelain", &porcelain, N_("machine-readable output")),
> @@ -2616,6 +2651,9 @@ int cmd_fetch(int argc,
>  	if (recurse_submodules_cli != RECURSE_SUBMODULES_DEFAULT)
>  		config.recurse_submodules = recurse_submodules_cli;
>  
> +	if (submodule_errors_cli != -1)
> +		config.submodule_errors = submodule_errors_cli;

And we override what we read from the configuration if we got a
command line override.

And the value in config.submodule_errors is used much later, in a
call to add_options_to_argv() we saw earlier, but this patch does
not touch the caller so we do not see the calling site.

I do not do submodules, so my expectation here may be a bit skewed,
but what happens when we configure fetch.submoduleErrors to warn,
but override it from the command line to fail?  .submodule_errors is
set to SUBMODULE_ERRORS_FAIL here?  As we saw, add_options_to_argv()
stuff --submodule-error=<setting> only when config.submodule_errors
is set to SUBMODULE_ERRORS_WARN, so we do not pass command line
override.  Is this desirable?  Don't we want to pass down not just
--submodule-error=warn but --submodule-error=fail if that is what
was given from the command line?  Or does it not matter because fail
is the default?

Thanks.



  reply	other threads:[~2026-07-10 22:21 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-10 12:26 [PATCH v3 0/2] fetch: make submodule fetch errors configurable Paulius Zaleckas
2026-07-10 12:26 ` [PATCH v3 1/2] submodule: fix premature failure in recursive submodule fetch Paulius Zaleckas
2026-07-10 12:26 ` [PATCH v3 2/2] fetch: add fetch.submoduleErrors to make submodule fetch errors non-fatal Paulius Zaleckas
2026-07-10 22:21   ` Junio C Hamano [this message]
2026-07-14 13:29     ` Paulius Zaleckas
2026-07-14 13:29 ` [PATCH v4 0/2] fetch: make submodule fetch errors configurable Paulius Zaleckas
2026-07-14 13:29   ` [PATCH v4 1/2] submodule: fix premature failure in recursive submodule fetch Paulius Zaleckas
2026-07-14 13:29   ` [PATCH v4 2/2] fetch: add fetch.submoduleErrors to make submodule fetch errors non-fatal Paulius Zaleckas
2026-07-14 15:34     ` Junio C Hamano
2026-07-14 17:14     ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=xmqqmrvybi5t.fsf@gitster.g \
    --to=gitster@pobox.com \
    --cc=avarab@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=glencbz@gmail.com \
    --cc=paulius.zaleckas@gmail.com \
    --cc=ps@pks.im \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.