Git development
 help / color / mirror / Atom feed
* [PATCH 0/4] fetch: add --must-have and remote.*.mustHave
@ 2026-04-08 14:36 Derrick Stolee via GitGitGadget
  2026-04-08 14:36 ` [PATCH 1/4] t5516: fix test order flakiness Derrick Stolee via GitGitGadget
                   ` (5 more replies)
  0 siblings, 6 replies; 54+ messages in thread
From: Derrick Stolee via GitGitGadget @ 2026-04-08 14:36 UTC (permalink / raw)
  To: git; +Cc: gitster, jonathantanmy, chooglen, ps, Derrick Stolee

Fetch negotiation aims to find enough information from haves and wants such
that the server can be reasonably confident that it will send all necessary
objects and not too many "extra" objects that the client already has.
However, this can break down if there are too many references, since Git
truncates the list of haves based on a few factors (a 256 count limit or the
server sending an ACK at the right time).

We already have the --negotiation-tip feature to focus the set of references
that are used in negotiation, but I feel like this is designed backwards.
I'd rather that we have a way to say "this is an important set of refs, but
feel free to add more refs if needed" than "only use these refs for
negotiation".

Here's an example that demonstrates the problem. In an internal monorepo,
developers work off of the 'main' branch so there are thousands of user
branches that each add a few commits different from the 'main' branch.
However, there is also a long-lived 'release' branch. This branch has a
first-parent history that is parallel to 'main' and each of those commits is
a merge whose second parent is a commit from 'main' that had a successful CI
run. There are additional changes in the 'release' branch merge commits that
add some changelog data, so there is a nontrivial set of novel blob content
in that branch and not just a different set of commits.

The problem we had was that our georeplication system was regularly fetching
from the origin and trying to get all data from all reachable branches. When
the 'release' branch updated, the client would run out of haves before
advertising its copy of the 'release' branch, but it would still list the
new 'release' tip as a want. The server would then think that the client had
never fetched that branch before and would send all of the changelog data
from the whole history of the repo. (This led to a lot of downstream
problems; we mitigated by setting a refspec that stopped fetching the
'release' branch, but this is not ideal.)

What I'd like is a mechanism to say "always advertise the client's version
of 'main' and 'release' but also opportunistically include some user
branches".

Based on my understanding, the '--negotiation-tip' option is close but not
quite what I want. I could have the client only advertise 'release' and
'main' and never advertise any user branches. But then we'd download all
content from each user branch every time it updates. Perhaps this would
happen even with opportunistic inclusion of more haves, but I'd like to
explore this area more.

There's also an issue that the '--negotiation-tip' feature doesn't seem to
have a config key that enables it without CLI arguments. This is something
that we could consider independently.

This patch series adds a new '--must-have' argument in the same places that
'--negotiation-tip' exists. This adds a set of references that will always
be included in the negotiation as haves, but then the rest of the
negotiation can proceed as normal. It also adds a new
'remote.<name>.mustHave' config option to enable this behavior without CLI
arguments.

The series is organized into four changes:

 1. The first change updates a test that started failing after I added some
    tests before it. This fix should be valuable on its own, but I need it
    for my tests to pass.
 2. The second change adds the --must-have option for fetch and tests it
    relative to --negotiation-tip.
 3. The third change adds the config option to enable --must-have by
    default. Any use in the CLI completely overrides the config option.
 4. The fourth change adds capabilities for the config to update negotiation
    during git push.

During development, I had briefly considered only using config values, but
that required some strange changes to care about the remote name in the
transport layer. This was most different in the 'git push' integration. When
I discovered the '--negotiation-tip' feature during the process, that gave
me a clear pattern to follow with the addition of a config on top.

I've CC'd some folks who have been working on or near the
'--negotiation-tip' feature for feedback as to how these things fit together
in the bigger picture.

Big picture questions to think about:

 * Is this a valuable addition to the fetch negotiation?
 * Is the interaction between --must-have and --negotiation-tip correct?
 * Is the "must have" name sensical to users? I expect that this only
   matters to experts, but I'm open to better names that could be more
   self-documenting.
 * Should we add a similar config key for --negotiation-tip?

Thanks, -Stolee

Derrick Stolee (4):
  t5516: fix test order flakiness
  fetch: add --must-have option for negotiation
  remote: add mustHave config as default for --must-have
  send-pack: pass --must-have for push negotiation

 Documentation/config/remote.adoc |  23 ++++++
 Documentation/fetch-options.adoc |  22 ++++++
 builtin/fetch.c                  |  14 +++-
 fetch-pack.c                     |  92 +++++++++++++++++++++--
 fetch-pack.h                     |  10 ++-
 remote.c                         |   6 ++
 remote.h                         |   1 +
 send-pack.c                      |  12 ++-
 send-pack.h                      |   1 +
 t/t5510-fetch.sh                 | 121 +++++++++++++++++++++++++++++++
 t/t5516-fetch-push.sh            |  17 ++++-
 transport.c                      |   5 +-
 transport.h                      |   6 ++
 13 files changed, 319 insertions(+), 11 deletions(-)


base-commit: 6e8d538aab8fe4dd07ba9fb87b5c7edcfa5706ad
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2085%2Fderrickstolee%2Fmust-have-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2085/derrickstolee/must-have-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/2085
-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 54+ messages in thread

end of thread, other threads:[~2026-05-14 12:41 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-08 14:36 [PATCH 0/4] fetch: add --must-have and remote.*.mustHave Derrick Stolee via GitGitGadget
2026-04-08 14:36 ` [PATCH 1/4] t5516: fix test order flakiness Derrick Stolee via GitGitGadget
2026-04-08 14:36 ` [PATCH 2/4] fetch: add --must-have option for negotiation Derrick Stolee via GitGitGadget
2026-04-08 14:36 ` [PATCH 3/4] remote: add mustHave config as default for --must-have Derrick Stolee via GitGitGadget
2026-04-08 14:36 ` [PATCH 4/4] send-pack: pass --must-have for push negotiation Derrick Stolee via GitGitGadget
2026-04-08 18:59 ` [PATCH 0/4] fetch: add --must-have and remote.*.mustHave Junio C Hamano
2026-04-09 12:53   ` Derrick Stolee
2026-04-15 15:14 ` [PATCH v2 0/7] fetch: rework negotiation tip options Derrick Stolee via GitGitGadget
2026-04-15 15:14   ` [PATCH v2 1/7] t5516: fix test order flakiness Derrick Stolee via GitGitGadget
2026-04-15 15:14   ` [PATCH v2 2/7] fetch: add --negotiation-restrict option Derrick Stolee via GitGitGadget
2026-04-15 21:57     ` Junio C Hamano
2026-04-19 23:00       ` Derrick Stolee
2026-04-20 10:32         ` Junio C Hamano
2026-04-20 11:35           ` Derrick Stolee
2026-04-15 15:14   ` [PATCH v2 3/7] transport: rename negotiation_tips Derrick Stolee via GitGitGadget
2026-04-20  8:11     ` Patrick Steinhardt
2026-04-15 15:14   ` [PATCH v2 4/7] remote: add remote.*.negotiationRestrict config Derrick Stolee via GitGitGadget
2026-04-15 19:16     ` Junio C Hamano
2026-04-15 15:14   ` [PATCH v2 5/7] fetch: add --negotiation-require option for negotiation Derrick Stolee via GitGitGadget
2026-04-15 19:50     ` Junio C Hamano
2026-04-21 18:06       ` Derrick Stolee
2026-04-20  8:11     ` Patrick Steinhardt
2026-04-20 11:41       ` Derrick Stolee
2026-04-15 15:14   ` [PATCH v2 6/7] remote: add negotiationRequire config as default for --negotiation-require Derrick Stolee via GitGitGadget
2026-04-15 15:14   ` [PATCH v2 7/7] send-pack: pass negotiation config in push Derrick Stolee via GitGitGadget
2026-04-22 15:25   ` [PATCH v3 0/7] fetch: rework negotiation tip options Derrick Stolee via GitGitGadget
2026-04-22 15:25     ` [PATCH v3 1/7] t5516: fix test order flakiness Derrick Stolee via GitGitGadget
2026-05-12 10:50       ` Matthew John Cheetham
2026-04-22 15:25     ` [PATCH v3 2/7] fetch: add --negotiation-restrict option Derrick Stolee via GitGitGadget
2026-05-12 11:11       ` Matthew John Cheetham
2026-05-12 14:23         ` Derrick Stolee
2026-04-22 15:25     ` [PATCH v3 3/7] transport: rename negotiation_tips Derrick Stolee via GitGitGadget
2026-05-12 11:30       ` Matthew John Cheetham
2026-05-12 14:33         ` Derrick Stolee
2026-04-22 15:25     ` [PATCH v3 4/7] remote: add remote.*.negotiationRestrict config Derrick Stolee via GitGitGadget
2026-05-12 12:29       ` Matthew John Cheetham
2026-05-12 14:52         ` Derrick Stolee
2026-04-22 15:25     ` [PATCH v3 5/7] fetch: add --negotiation-include option for negotiation Derrick Stolee via GitGitGadget
2026-05-12 14:38       ` Matthew John Cheetham
2026-05-12 16:54         ` Derrick Stolee
2026-04-22 15:25     ` [PATCH v3 6/7] remote: add remote.*.negotiationInclude config Derrick Stolee via GitGitGadget
2026-05-12 14:54       ` Matthew John Cheetham
2026-05-12 17:55         ` Derrick Stolee
2026-04-22 15:25     ` [PATCH v3 7/7] send-pack: pass negotiation config in push Derrick Stolee via GitGitGadget
2026-05-12 15:14       ` Matthew John Cheetham
2026-05-14 12:41     ` [PATCH v4 0/8] fetch: rework negotiation tip options Derrick Stolee via GitGitGadget
2026-05-14 12:41       ` [PATCH v4 1/8] t5516: fix test order flakiness Derrick Stolee via GitGitGadget
2026-05-14 12:41       ` [PATCH v4 2/8] fetch: add --negotiation-restrict option Derrick Stolee via GitGitGadget
2026-05-14 12:41       ` [PATCH v4 3/8] transport: rename negotiation_tips Derrick Stolee via GitGitGadget
2026-05-14 12:41       ` [PATCH v4 4/8] remote: add remote.*.negotiationRestrict config Derrick Stolee via GitGitGadget
2026-05-14 12:41       ` [PATCH v4 5/8] negotiator: add have_sent() interface Derrick Stolee via GitGitGadget
2026-05-14 12:41       ` [PATCH v4 6/8] fetch: add --negotiation-include option for negotiation Derrick Stolee via GitGitGadget
2026-05-14 12:41       ` [PATCH v4 7/8] remote: add remote.*.negotiationInclude config Derrick Stolee via GitGitGadget
2026-05-14 12:41       ` [PATCH v4 8/8] send-pack: pass negotiation config in push Derrick Stolee via GitGitGadget

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox