]> git.ipfire.org Git - thirdparty/git.git/commitdiff
fetch: avoid ls-refs only to ask for HEAD symref update
authorJeff King <peff@peff.net>
Sun, 9 Mar 2025 03:20:16 +0000 (22:20 -0500)
committerJunio C Hamano <gitster@pobox.com>
Mon, 10 Mar 2025 20:13:46 +0000 (13:13 -0700)
When we fetch from a configured remote, we may try to update the local
refs/remotes/<origin>/HEAD, and so we ask the server to advertise its
HEAD to us.

But if we aren't otherwise asking about any refs at all, then we know
this HEAD update can never happen! To consider a new value for HEAD,
the set_head() function uses guess_remote_head(). And even if it sees an
explicit symref value for HEAD, it will only report that as a match if
we also saw that remote ref advertised, and it mapped to a local
tracking ref via get_fetch_map().

In other words, a fetch like this:

  git fetch origin $exact_oid:refs/heads/foo

can never update HEAD, because we will never have fetched (nor even see
the advertisement for) the ref that HEAD points to.

Currently the command above will still call ls-refs to ask about the
HEAD, even though it is pointless. This patch teaches it to skip the
ls-refs call entirely in this case, which avoids a round-trip to the
server.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/fetch.c
t/t5702-protocol-v2.sh

index 6ab101fa6dfb45366e1c190104beb465b5b6229d..c26866e6745ef2d990025ade49f4be356d69e228 100644 (file)
@@ -1782,11 +1782,10 @@ static int do_fetch(struct transport *transport,
                            "refs/tags/");
        }
 
-       if (uses_remote_tracking(transport, rs)) {
-               must_list_refs = 1;
+       if (must_list_refs &&
+           uses_remote_tracking(transport, rs))
                strvec_push(&transport_ls_refs_options.ref_prefixes,
                            "HEAD");
-       }
 
        if (must_list_refs) {
                trace2_region_enter("fetch", "remote_refs", the_repository);
index 626deb05f046ca3fa07c0d08c35170decfe1d1d3..4d0cbe9872346410b7072ec26f9683ae6fe57126 100755 (executable)
@@ -708,6 +708,19 @@ test_expect_success 'exact oid fetch with tag following' '
        git -C exact-oid-tags rev-parse --verify my-tag
 '
 
+test_expect_success 'exact oid fetch avoids pointless HEAD request' '
+       git init exact-oid-head &&
+       git -C exact-oid-head remote add origin ../prefix-parent &&
+
+       commit=$(git -C prefix-parent rev-parse --verify HEAD) &&
+
+       test_when_finished "rm -f log" &&
+       GIT_TRACE_PACKET="$(pwd)/log" \
+               git -C exact-oid-head fetch --no-tags origin \
+                       $commit:refs/heads/exact &&
+       test_grep ! command=ls-refs log
+'
+
 test_expect_success 'fetch supports various ways of have lines' '
        rm -rf server client trace &&
        git init server &&