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

Re: The transfer.hideRefs of the upload-pack process does not work properly

From
SSURA <surak8806@gmail.com>
Date
Feb 28, 2025, 02:32 UTC
Message-ID
<CAD6AYr84KuBb5N-LVBQo-6Gq2Ms3JKQCk0gyO8i=N8gp3whe_Q@mail.gmail.com>
In-Reply-To
<Z8D/aiqN5e/aRSn7@nand.local>
Taylor Blau <me@ttaylorr.com> 于2025年2月28日周五 08:12写道:
>
> (There's a parallel discussion going on in [1], so it isn't entirely
> clear which thread to respond to. Since it seems a little premature to
> comment on the patch itself, I'll respond here.)

So sorry, I used another email address to submit the patch, it is indeed a bit early

Show 63 quoted lines
> On Thu, Feb 27, 2025 at 03:24:07PM +0800, SURA wrote:
> > I found that packed refs are excluded by the transfer.hideRefs front
> > match, while loose refs use full match (when transfer.hideRefs ends
> > with '/', it is prefix match, which is normal)
> >
> > When the server uses git, after setting transfer.hideRefs, the
> > references that the client can see before and after server repo gc are
> > different
>
> It's true that the low-level loose references iterator does not know how
> to handle excluded patterns, and that is by design. In the packed-refs
> case, we can skip over whole sections of the packed-refs file according
> to which patterns are excluded.
>
> But in the loose references case, we haven't implemented anything like
> that to skip over, e.g. enumerating the contents of
> "$GIT_DIR/refs/heads/foo" when "refs/heads/foo/" is excluded. (As an
> aside, this is something that we could do, it just hasn't been
> implemented yet).
>
> So in practice today the only way to exclude loose references according
> to some set of exclusion patterns would be to filter them out as we
> iterate over them. But that is the caller's responsibility, as we see in
> a handful of comments in refs.h which say "any pattern in
> 'exclude_patterns' [is] omitted on a best-effort basis".
>
> So upload-pack / etc. will see all loose references, and it filters out
> the ones which it's supposed to hide via:
>
>     upload_pack() -> for_each_namespaced_ref_1() -> send_ref() ->
>     write_v0_ref() -> mark_our_ref() -> ref_is_hidden()
>
> , where mark_our_ref() tosses out references that the low-level refs
> iterator gave back to it which match one of the excluded patterns.
>
> And there we have ref_is_hidden() doing the following for each hidden
> pattern:
>
>     if (subject &&
>         skip_prefix(subject, match, &p) &&
>         (!*p || *p == '/'))
>      return !neg;
>
> So if the reference either matches the pattern exactly, or matches up to
> a '/', then it is hidden and thus not advertised.
>
> I have to imagine I'm missing something, but perhaps it would be useful
> if you could provide a reproduction script that demonstrates what you're
> seeing.
>
> > It seems that 59c35fa accidentally damaged upload-pack when optimizing
> > git for-each-ref
>
> No. 59c35fac54 (refs/packed-backend.c: implement jump lists to avoid
> excluded pattern(s), 2023-07-10) predates any behavior changes in
> upload-pack, which were introduced later on in 18b6b1b5c5
> (upload-pack.c: avoid enumerating hidden refs where possible,
> 2023-07-10).
>
> Thanks,
> Taylor
>
> [1]: https://lore.kernel.org/git/MA0P287MB06412DF70BCDA0D99641129FE4CD2@MA0P287MB0641.INDP287.PROD.OUTLOOK.COM/T/#t
I shouldn't have mentioned the '/' suffix, it's confusing

My previous description was not clear enough. The early hiding according to exclude_patterns in packed_ref_iterator_begin seems to be designed for git for-each-ref's exclude. It is different from the ref_hidden matching rule used by upload-pack.

I provide a reproducible step to make it clear
------

# create git repo $ mkdir sura-repo && cd sura-repo $ git init

# create one commit $ echo "hello" > file-001 $ git add . && git commit -m "init repo"

# create some refs $ git checkout -b sura $ git checkout -b sura-001 $ git checkout -b sura-002 $ git checkout -b sura-003

# show refs $ git for-each-ref d0205e0d0a0a7a6d1a712afb3734ad3e88eeda1c commit refs/heads/master d0205e0d0a0a7a6d1a712afb3734ad3e88eeda1c commit refs/heads/sura d0205e0d0a0a7a6d1a712afb3734ad3e88eeda1c commit refs/heads/sura-001 d0205e0d0a0a7a6d1a712afb3734ad3e88eeda1c commit refs/heads/sura-002 d0205e0d0a0a7a6d1a712afb3734ad3e88eeda1c commit refs/heads/sura-003

# upload-pack, normal, hide 'refs/heads/sura' $ git -c transfer.hiderefs=refs/heads/sura upload-pack .git 0103d0205e0d0a0a7a6d1a712afb3734ad3e88eeda1c HEADmulti_ack thin-pack side-band side-band-64k ofs-delta shallow deepen-since deepen-not deepen-relative no-progress include-tag multi_ack_detailed symref=HEAD:refs/heads/sura object-format=sha1 agent=git/2.46.0 003fd0205e0d0a0a7a6d1a712afb3734ad3e88eeda1c refs/heads/master 0041d0205e0d0a0a7a6d1a712afb3734ad3e88eeda1c refs/heads/sura-001 0041d0205e0d0a0a7a6d1a712afb3734ad3e88eeda1c refs/heads/sura-002 0041d0205e0d0a0a7a6d1a712afb3734ad3e88eeda1c refs/heads/sura-003 0000

# gc make loose refs to packed refs $ git gc

# then upload-pack $ git -c transfer.hiderefs=refs/heads/sura upload-pack .git 0103d0205e0d0a0a7a6d1a712afb3734ad3e88eeda1c HEADmulti_ack thin-pack side-band side-band-64k ofs-delta shallow deepen-since deepen-not deepen-relative no-progress include-tag multi_ack_detailed symref=HEAD:refs/heads/sura object-format=sha1 agent=git/2.46.0 003fd0205e0d0a0a7a6d1a712afb3734ad3e88eeda1c refs/heads/master 0000

Previous: Taylor BlauNext: Jeff King
Message 3 of 10 in “The transfer.hideRefs of the upload-pack process does not work properly”
  1. SURAFeb 27, 2025
  2. Taylor BlauFeb 28, 2025
  3. SURAFeb 28, 2025
  4. Jeff KingMar 4, 2025
  5. Jeff KingMar 4, 2025
  6. Patrick SteinhardtMar 4, 2025
  7. Taylor BlauMar 4, 2025
  8. Taylor BlauMar 6, 2025
  9. Taylor BlauMar 5, 2025
  10. Junio C HamanoMar 5, 2025

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.