git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v4 4/8] remote: add remote.*.negotiationRestrict config

From
Matthew John Cheetham <mjcheetham@outlook.com>
Date
May 18, 2026, 16:46 UTC
Message-ID
<VI0PR03MB1163495D24C68C59B8CE02105C0032@VI0PR03MB11634.eurprd03.prod.outlook.com>
In-Reply-To
<a14c568a1fd3680e40b70cf9ca14fd2a5305df5e.1778762495.git.gitgitgadget@gmail.com>
On 2026-05-14 13:41, Derrick Stolee via GitGitGadget wrote:
Show 54 quoted lines
> From: Derrick Stolee <stolee@gmail.com>
> 
> In a previous change, the --negotiation-restrict command-line option of 'git
> fetch' was added as a synonym of --negotiation-tip. Both of these options
> restrict the set of 'haves' the client can send as part of negotiation.
> 
> This was previously not available via a configuration option. Add a new
> 'remote.<name>.negotiationRestrict' multi-valued config option that updates
> 'git fetch <name>' to use these restrictions by default.
> 
> If the user provides even one --negotiation-restrict argument, then the
> config is ignored.
> 
> An empty value resets the value list to allow ignoring earlier config
> values, such as those that might be set in system or global config.
> 
> Signed-off-by: Derrick Stolee <stolee@gmail.com>
> ---
>   Documentation/config/remote.adoc | 18 ++++++++++++++++++
>   builtin/fetch.c                  | 28 +++++++++++++++++++++-------
>   remote.c                         |  5 +++++
>   remote.h                         |  1 +
>   t/t5510-fetch.sh                 | 26 ++++++++++++++++++++++++++
>   5 files changed, 71 insertions(+), 7 deletions(-)
> 
> diff --git a/Documentation/config/remote.adoc b/Documentation/config/remote.adoc
> index 91e46f66f5..4dcf81fbce 100644
> --- a/Documentation/config/remote.adoc
> +++ b/Documentation/config/remote.adoc
> @@ -107,6 +107,24 @@ priority configuration file (e.g. `.git/config` in a repository) to clear
>   the values inherited from a lower priority configuration files (e.g.
>   `$HOME/.gitconfig`).
>   
> +remote.<name>.negotiationRestrict::
> +	When negotiating with this remote during `git fetch`, restrict the
> +	commits advertised as "have" lines to only those reachable from refs
> +	matching the given patterns.  This multi-valued config option behaves
> +	like `--negotiation-restrict` on the command line.
> ++
> +Each value is either an exact ref name (e.g. `refs/heads/release`) or a
> +glob pattern (e.g. `refs/heads/release/*`).  The pattern syntax is the
> +same as for `--negotiation-restrict`.
> ++
> +These config values are used as defaults for the `--negotiation-restrict`
> +command-line option.  If `--negotiation-restrict` (or its synonym
> +`--negotiation-tip`) is specified on the command line, then the config
> +values are not used.
> ++
> +Blank values signal to ignore all previous values, allowing a reset of
> +the list from broader config scenarios.
> +
>   remote.<name>.followRemoteHEAD::
>   	How linkgit:git-fetch[1] should handle updates to `remotes/<name>/HEAD`
>   	when fetching using the configured refspecs of a remote.

Good - now we don't talk about 'git push' before we have wired that functionality up.

Show 24 quoted lines
> diff --git a/builtin/fetch.c b/builtin/fetch.c
> index 2ba0051d52..a957739f37 100644
> --- a/builtin/fetch.c
> +++ b/builtin/fetch.c
> @@ -1601,6 +1601,19 @@ static struct transport *prepare_transport(struct remote *remote, int deepen,
>   		else
>   			warning(_("ignoring %s because the protocol does not support it"),
>   				"--negotiation-restrict");
> +	} else if (remote->negotiation_restrict.nr) {
> +		struct string_list_item *item;
> +		for_each_string_list_item(item, &remote->negotiation_restrict)
> +			string_list_append(&negotiation_restrict, item->string);
> +		if (transport->smart_options)
> +			add_negotiation_restrict_tips(transport->smart_options);
> +		else {
> +			struct strbuf config_name = STRBUF_INIT;
> +			strbuf_addf(&config_name, "remote.%s.negotiationRestrict", remote->name);
> +			warning(_("ignoring %s because the protocol does not support it"),
> +				config_name.buf);
> +			strbuf_release(&config_name);
> +		}
>   	}
>   	return transport;
>   }
Unchanged from v3 and still reads cleanly. Good.
Show 34 quoted lines
> @@ -2658,10 +2671,6 @@ int cmd_fetch(int argc,
>   		config.display_format = DISPLAY_FORMAT_PORCELAIN;
>   	}
>   
> -	if (negotiate_only && !negotiation_restrict.nr)
> -		die(_("%s needs one or more %s"), "--negotiate-only",
> -		    "--negotiation-restrict=*");
> -
>   	if (deepen_relative) {
>   		if (deepen_relative < 0)
>   			die(_("negative depth in --deepen is not supported"));
> @@ -2749,14 +2758,19 @@ int cmd_fetch(int argc,
>   		if (!remote)
>   			die(_("must supply remote when using --negotiate-only"));
>   		gtransport = prepare_transport(remote, 1, &filter_options);
> -		if (gtransport->smart_options) {
> -			gtransport->smart_options->acked_commits = &acked_commits;
> -		} else {
> +
> +		if (!gtransport->smart_options) {
>   			warning(_("protocol does not support --negotiate-only, exiting"));
>   			result = 1;
>   			trace2_region_leave("fetch", "negotiate-only", the_repository);
>   			goto cleanup;
>   		}
> +		if (!gtransport->smart_options->negotiation_restrict_tips)
> +			die(_("%s needs one or more %s"), "--negotiate-only",
> +			    "--negotiation-restrict=*");
> +
> +		gtransport->smart_options->acked_commits = &acked_commits;
> +
>   		if (server_options.nr)
>   			gtransport->server_options = &server_options;
>   		result = transport_fetch_refs(gtransport, NULL);

This is nice! Addressed my concerns in v3 about the wrong message being shown, and makes it clearer with an up-front check for the protocol support.

Show 30 quoted lines
> diff --git a/remote.c b/remote.c
> index 7ca2a6501b..620086e16e 100644
> --- a/remote.c
> +++ b/remote.c
> @@ -152,6 +152,7 @@ static struct remote *make_remote(struct remote_state *remote_state,
>   	refspec_init_push(&ret->push);
>   	refspec_init_fetch(&ret->fetch);
>   	string_list_init_dup(&ret->server_options);
> +	string_list_init_dup(&ret->negotiation_restrict);
>   
>   	ALLOC_GROW(remote_state->remotes, remote_state->remotes_nr + 1,
>   		   remote_state->remotes_alloc);
> @@ -179,6 +180,7 @@ static void remote_clear(struct remote *remote)
>   	FREE_AND_NULL(remote->http_proxy);
>   	FREE_AND_NULL(remote->http_proxy_authmethod);
>   	string_list_clear(&remote->server_options, 0);
> +	string_list_clear(&remote->negotiation_restrict, 0);
>   }
>   
>   static void add_merge(struct branch *branch, const char *name)
> @@ -562,6 +564,9 @@ static int handle_config(const char *key, const char *value,
>   	} else if (!strcmp(subkey, "serveroption")) {
>   		return parse_transport_option(key, value,
>   					      &remote->server_options);
> +	} else if (!strcmp(subkey, "negotiationrestrict")) {
> +		return parse_transport_option(key, value,
> +					      &remote->negotiation_restrict);
>   	} else if (!strcmp(subkey, "followremotehead")) {
>   		const char *no_warn_branch;
>   		if (!strcmp(value, "never"))

Good - reusing the parse_transport_option() as suggested makes this a smaller diff and consistent with 'serveroption' above.

Show 49 quoted lines
> diff --git a/remote.h b/remote.h
> index fc052945ee..e6ec37c393 100644
> --- a/remote.h
> +++ b/remote.h
> @@ -117,6 +117,7 @@ struct remote {
>   	char *http_proxy_authmethod;
>   
>   	struct string_list server_options;
> +	struct string_list negotiation_restrict;
>   
>   	enum follow_remote_head_settings follow_remote_head;
>   	const char *no_warn_branch;
> diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
> index dc3ce56d84..eff3ce8e2d 100755
> --- a/t/t5510-fetch.sh
> +++ b/t/t5510-fetch.sh
> @@ -1485,6 +1485,32 @@ test_expect_success '--negotiation-restrict and --negotiation-tip can be mixed'
>   	check_negotiation_tip
>   '
>   
> +test_expect_success 'remote.<name>.negotiationRestrict used as default' '
> +	setup_negotiation_tip server server 0 &&
> +
> +	# test the reset of the list on an empty value
> +	git -C client config --add remote.origin.negotiationRestrict alpha_2 &&
> +	git -C client config --add remote.origin.negotiationRestrict "" &&
> +	git -C client config --add remote.origin.negotiationRestrict alpha_1 &&
> +	git -C client config --add remote.origin.negotiationRestrict beta_1 &&
> +	GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
> +		origin alpha_s beta_s &&
> +	check_negotiation_tip
> +'
> +
> +test_expect_success 'CLI --negotiation-restrict overrides remote config' '
> +	setup_negotiation_tip server server 0 &&
> +	git -C client config --add remote.origin.negotiationRestrict alpha_1 &&
> +	git -C client config --add remote.origin.negotiationRestrict beta_1 &&
> +	ALPHA_1=$(git -C client rev-parse alpha_1) &&
> +	GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
> +		--negotiation-restrict=alpha_1 \
> +		origin alpha_s beta_s &&
> +	test_grep "fetch> have $ALPHA_1" trace &&
> +	BETA_1=$(git -C client rev-parse beta_1) &&
> +	test_grep ! "fetch> have $BETA_1" trace
> +'
> +
>   test_expect_success SYMLINKS 'clone does not get confused by a D/F conflict' '
>   	git init df-conflict &&
>   	(
Again, this patch looks good to me and addresses my previous comments.

Thanks, Matthew

Previous: Derrick Stolee via GitGitGadgetNext: Derrick Stolee via GitGitGadget
Message 54 of 86 in “fetch: add --must-have and remote.*.mustHave”
  1. 0/4 fetch: add --must-have and remote.*.mustHaveDerrick Stolee via GitGitGadget, Apr 8, 2026
  2. 1/4 t5516: fix test order flakinessDerrick Stolee via GitGitGadget, Apr 8, 2026
  3. 2/4 fetch: add --must-have option for negotiationDerrick Stolee via GitGitGadget, Apr 8, 2026
  4. 3/4 remote: add mustHave config as default for --must-haveDerrick Stolee via GitGitGadget, Apr 8, 2026
  5. 4/4 send-pack: pass --must-have for push negotiationDerrick Stolee via GitGitGadget, Apr 8, 2026
  6. Junio C HamanoApr 8, 2026
  7. Derrick StoleeApr 9, 2026
  8. 0/7 fetch: rework negotiation tip optionsDerrick Stolee via GitGitGadget, Apr 15, 2026
  9. 1/7 t5516: fix test order flakinessDerrick Stolee via GitGitGadget, Apr 15, 2026
  10. 2/7 fetch: add --negotiation-restrict optionDerrick Stolee via GitGitGadget, Apr 15, 2026
  11. Junio C HamanoApr 15, 2026
  12. Derrick StoleeApr 19, 2026
  13. Junio C HamanoApr 20, 2026
  14. Derrick StoleeApr 20, 2026
  15. 3/7 transport: rename negotiation_tipsDerrick Stolee via GitGitGadget, Apr 15, 2026
  16. Patrick SteinhardtApr 20, 2026
  17. 4/7 remote: add remote.*.negotiationRestrict configDerrick Stolee via GitGitGadget, Apr 15, 2026
  18. Junio C HamanoApr 15, 2026
  19. 5/7 fetch: add --negotiation-require option for negotiationDerrick Stolee via GitGitGadget, Apr 15, 2026
  20. Junio C HamanoApr 15, 2026
  21. Derrick StoleeApr 21, 2026
  22. Patrick SteinhardtApr 20, 2026
  23. Derrick StoleeApr 20, 2026
  24. 6/7 remote: add negotiationRequire config as default for --negotiation-requireDerrick Stolee via GitGitGadget, Apr 15, 2026
  25. 7/7 send-pack: pass negotiation config in pushDerrick Stolee via GitGitGadget, Apr 15, 2026
  26. 0/7 fetch: rework negotiation tip optionsDerrick Stolee via GitGitGadget, Apr 22, 2026
  27. 1/7 t5516: fix test order flakinessDerrick Stolee via GitGitGadget, Apr 22, 2026
  28. Matthew John CheethamMay 12, 2026
  29. 2/7 fetch: add --negotiation-restrict optionDerrick Stolee via GitGitGadget, Apr 22, 2026
  30. Matthew John CheethamMay 12, 2026
  31. Derrick StoleeMay 12, 2026
  32. 3/7 transport: rename negotiation_tipsDerrick Stolee via GitGitGadget, Apr 22, 2026
  33. Matthew John CheethamMay 12, 2026
  34. Derrick StoleeMay 12, 2026
  35. 4/7 remote: add remote.*.negotiationRestrict configDerrick Stolee via GitGitGadget, Apr 22, 2026
  36. Matthew John CheethamMay 12, 2026
  37. Derrick StoleeMay 12, 2026
  38. 5/7 fetch: add --negotiation-include option for negotiationDerrick Stolee via GitGitGadget, Apr 22, 2026
  39. Matthew John CheethamMay 12, 2026
  40. Derrick StoleeMay 12, 2026
  41. 6/7 remote: add remote.*.negotiationInclude configDerrick Stolee via GitGitGadget, Apr 22, 2026
  42. Matthew John CheethamMay 12, 2026
  43. Derrick StoleeMay 12, 2026
  44. 7/7 send-pack: pass negotiation config in pushDerrick Stolee via GitGitGadget, Apr 22, 2026
  45. Matthew John CheethamMay 12, 2026
  46. 0/8 fetch: rework negotiation tip optionsDerrick Stolee via GitGitGadget, May 14, 2026
  47. 1/8 t5516: fix test order flakinessDerrick Stolee via GitGitGadget, May 14, 2026
  48. Matthew John CheethamMay 18, 2026
  49. 2/8 fetch: add --negotiation-restrict optionDerrick Stolee via GitGitGadget, May 14, 2026
  50. Matthew John CheethamMay 18, 2026
  51. 3/8 transport: rename negotiation_tipsDerrick Stolee via GitGitGadget, May 14, 2026
  52. Matthew John CheethamMay 18, 2026
  53. 4/8 remote: add remote.*.negotiationRestrict configDerrick Stolee via GitGitGadget, May 14, 2026
  54. Matthew John CheethamMay 18, 2026
  55. 5/8 negotiator: add have_sent() interfaceDerrick Stolee via GitGitGadget, May 14, 2026
  56. Matthew John CheethamMay 18, 2026
  57. 6/8 fetch: add --negotiation-include option for negotiationDerrick Stolee via GitGitGadget, May 14, 2026
  58. Matthew John CheethamMay 18, 2026
  59. 7/8 remote: add remote.*.negotiationInclude configDerrick Stolee via GitGitGadget, May 14, 2026
  60. Matthew John CheethamMay 18, 2026
  61. 8/8 send-pack: pass negotiation config in pushDerrick Stolee via GitGitGadget, May 14, 2026
  62. Matthew John CheethamMay 18, 2026
  63. Matthew John CheethamMay 18, 2026
  64. Derrick StoleeMay 18, 2026
  65. 0/8 fetch: rework negotiation tip optionsDerrick Stolee via GitGitGadget, May 18, 2026
  66. 2/8 fetch: add --negotiation-restrict optionDerrick Stolee via GitGitGadget, May 18, 2026
  67. 3/8 transport: rename negotiation_tipsDerrick Stolee via GitGitGadget, May 18, 2026
  68. 4/8 remote: add remote.*.negotiationRestrict configDerrick Stolee via GitGitGadget, May 18, 2026
  69. 5/8 negotiator: add have_sent() interfaceDerrick Stolee via GitGitGadget, May 18, 2026
  70. 6/8 fetch: add --negotiation-include option for negotiationDerrick Stolee via GitGitGadget, May 18, 2026
  71. 7/8 remote: add remote.*.negotiationInclude configDerrick Stolee via GitGitGadget, May 18, 2026
  72. 8/8 send-pack: pass negotiation config in pushDerrick Stolee via GitGitGadget, May 18, 2026
  73. 1/8 t5516: fix test order flakinessDerrick Stolee via GitGitGadget, May 18, 2026
  74. Matthew John CheethamMay 19, 2026
  75. Derrick StoleeMay 19, 2026
  76. 0/8 fetch: rework negotiation tip optionsDerrick Stolee via GitGitGadget, May 19, 2026
  77. 1/8 t5516: fix test order flakinessDerrick Stolee via GitGitGadget, May 19, 2026
  78. 2/8 fetch: add --negotiation-restrict optionDerrick Stolee via GitGitGadget, May 19, 2026
  79. 3/8 transport: rename negotiation_tipsDerrick Stolee via GitGitGadget, May 19, 2026
  80. 4/8 remote: add remote.*.negotiationRestrict configDerrick Stolee via GitGitGadget, May 19, 2026
  81. 5/8 negotiator: add have_sent() interfaceDerrick Stolee via GitGitGadget, May 19, 2026
  82. 6/8 fetch: add --negotiation-include option for negotiationDerrick Stolee via GitGitGadget, May 19, 2026
  83. 7/8 remote: add remote.*.negotiationInclude configDerrick Stolee via GitGitGadget, May 19, 2026
  84. 8/8 send-pack: pass negotiation config in pushDerrick Stolee via GitGitGadget, May 19, 2026
  85. Matthew John CheethamMay 19, 2026
  86. Junio C HamanoMay 20, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.