From: Karthik Nayak Date: Fri, 09 Oct 2026 22:16:42 GMT Subject: Re: [PATCH] fetch: commit references fetched before backfilling tags Message-ID: In-Reply-To: Justin Tobler writes: > On 26/10/09 01:26PM, Patrick Steinhardt wrote: >> On Fri, Oct 09, 2026 at 12:10:37AM +0200, Karthik Nayak wrote: >> > In 0e358de64a (fetch: use batched reference updates, 2025-05-19), the >> > fetch code was modified to use batched updates to provide a good >> > performance improvement. Wherein batched updates were used to fetch both >> > references and backfill tags. >> > >> > When using batched updates, the references aren't yet committed to disk >> > when we start backfilling tags. This means in situations such as shallow >> > fetching the negotiation during backfilling tags, the client doesn't >> > have any references to report in the 'have' section. Since backfilling >> > doesn't use a depth limit, this can cause the server to send all the >> > objects present in the repository. >> >> So in my own words: the server sends the reference, we queue them in a >> transaction, but don't commit it yet. We then try to backfill tags, and >> because we don't have the refs committed yet the backfill will think we >> don't have any of the relevant commits that those tags point to. >> Consequently, the packfile negotiation will result in way more objects >> being fetched than necessary. >> >> This makes me wonder why we even do a proper fetch. In theory, we could >> basically just ask the server for the individual tagged objects without >> performing any negotiation, right? >> >> Or... well, would that work with nested annotated tags? No idea. > > IIUC, when we backfill tags, we only fetch tags that reference objects > that we have locally. The server advertises the tag reference OID and > its recursively peeled non-tag OID so the client can figure this out: > > efe1aaafb77990c4f023cec81b198e0af55bbfb5 refs/tags/foo > c8dd1e3bb1152844983558802a52c9e4c17652b4 refs/tags/foo^{} > > So because there could be nested annontated tags, I think we would need > to fetch to get the intermediate objects. > > -Justin Yup exactly this. Afaik the protocol also works by transferring the set of objects that form the closure of between have <> want. So for: foo -> [tag A] -> [tag B] -> [commit C] We cannot simply request for A without saying we have C. We have C and we know it, but the haves are obtained from the committed refs, so until refs are written to disk we never advertise C.