From: Matthew John Cheetham Date: Tue, 12 May 2026 14:54:40 GMT Subject: Re: [PATCH v3 6/7] remote: add remote.*.negotiationInclude config Message-ID: In-Reply-To: On 2026-04-22 16:25, Derrick Stolee via GitGitGadget wrote: > From: Derrick Stolee > > Add a new 'remote..negotiationInclude' multi-valued config option that > provides default values for --negotiation-include when no > --negotiation-include arguments are specified over the command line. This > is a mirror of how 'remote..negotiationRestrict' specifies defaults > for the --negotiation-restrict arguments. > > Each value is either an exact ref name or a glob pattern whose tips should > always be sent as 'have' lines during negotiation. The config values are > resolved through the same resolve_negotiation_include() codepath as the CLI > options. > > This option is additive with the normal negotiation process: the negotiation > algorithm still runs and advertises its own selected commits, but the refs > matching the config are sent unconditionally on top of those heuristically > selected commits. > > Similar to the negotiationRestrict config, 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 > --- > Documentation/config/remote.adoc | 27 ++++++++++++++++++ > Documentation/fetch-options.adoc | 4 +++ > builtin/fetch.c | 10 +++++++ > remote.c | 8 ++++++ > remote.h | 1 + > t/t5510-fetch.sh | 49 ++++++++++++++++++++++++++++++++ > 6 files changed, 99 insertions(+) This patch is a mirror of patch 4 that added the remote config for negotiateRestrict. Some of the same comments apply here too: - reusing `parse_transport_option()` vs inline resetting the list - values could be commit SHAs as well as refs/globs > diff --git a/Documentation/config/remote.adoc b/Documentation/config/remote.adoc > index f1d889d03e..44de6d3c1f 100644 > --- a/Documentation/config/remote.adoc > +++ b/Documentation/config/remote.adoc > @@ -126,6 +126,33 @@ values are not used. > Blank values signal to ignore all previous values, allowing a reset of > the list from broader config scenarios. > > +remote..negotiationInclude:: > + When negotiating with this remote during `git fetch` and `git push`, > + the client advertises a list of commits that exist locally. In > + repos with many references, this list of "haves" can be truncated. > + Depending on data shape, dropping certain references may be > + expensive. This multi-valued config option specifies ref patterns > + whose tips should always be sent as "have" commits during fetch > + negotiation with this remote. > ++ > +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`. Should this say "..same as for `--negotiation-include`"? This way each `remote..negotiationX` doc cross-references the corresponding `--negotiation-X` command line option. > diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh > index 4316f8d4ea..db73ed5379 100755 > --- a/t/t5510-fetch.sh > +++ b/t/t5510-fetch.sh > @@ -1577,6 +1577,55 @@ test_expect_success '--negotiation-include avoids duplicates with negotiator' ' > test_line_count = 1 matches > ' > > +test_expect_success 'remote..negotiationInclude used as default for --negotiation-include' ' > + test_when_finished rm -f trace && > + setup_negotiation_tip server server 0 && > + > + # test the reset of the list on an empty value > + git -C client config --add remote.origin.negotiationInclude refs/tags/alpha_1 && > + git -C client config --add remote.origin.negotiationInclude "" && > + git -C client config --add remote.origin.negotiationInclude refs/tags/beta_1 && > + GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \ > + --negotiation-restrict=alpha_1 \ > + origin alpha_s beta_s && > + > + ALPHA_1=$(git -C client rev-parse alpha_1) && > + test_grep "fetch> have $ALPHA_1" trace && > + BETA_1=$(git -C client rev-parse beta_1) && > + test_grep "fetch> have $BETA_1" trace > +' This test sets up the include list as [alpha_1, "", beta_1] which after the reset should become [beta_1], but the assertions in the test only check that alpha_1 (sent via the --negotiation-restrict option) and beta_1 (sent via the include) appear. If the reset of the list didn't work then the test still passes because alpha_1 is sent via the CLI option. > +test_expect_success 'remote..negotiationInclude works with glob patterns' ' > + test_when_finished rm -f trace && > + setup_negotiation_tip server server 0 && > + > + git -C client config --add remote.origin.negotiationInclude "refs/tags/beta_*" && > + GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \ > + --negotiation-restrict=alpha_1 \ > + origin alpha_s beta_s && > + > + BETA_1=$(git -C client rev-parse beta_1) && > + test_grep "fetch> have $BETA_1" trace && > + BETA_2=$(git -C client rev-parse beta_2) && > + test_grep "fetch> have $BETA_2" trace > +' > + > +test_expect_success 'CLI --negotiation-include overrides remote..negotiationInclude' ' > + test_when_finished rm -f trace && > + setup_negotiation_tip server server 0 && > + > + git -C client config --add remote.origin.negotiationInclude refs/tags/beta_2 && > + GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \ > + --negotiation-restrict=alpha_1 \ > + --negotiation-include=refs/tags/beta_1 \ > + origin alpha_s beta_s && > + > + BETA_1=$(git -C client rev-parse beta_1) && > + test_grep "fetch> have $BETA_1" trace && > + BETA_2=$(git -C client rev-parse beta_2) && > + test_grep ! "fetch> have $BETA_2" trace > +' > + > test_expect_success SYMLINKS 'clone does not get confused by a D/F conflict' ' > git init df-conflict && > ( Thanks, Matthew