From: Junio C Hamano Date: Fri, 6 Dec 2024 08:08:00 +0000 (+0900) Subject: fetch: do not ask for HEAD unnecessarily X-Git-Tag: v2.48.0-rc1~29^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6c915c3f85;p=thirdparty%2Fgit.git fetch: do not ask for HEAD unnecessarily In 3f763ddf28 (fetch: set remote/HEAD if it does not exist, 2024-11-22), git-fetch learned to opportunistically set $REMOTE/HEAD when fetching by always asking for remote HEAD, in the hope that it will help setting refs/remotes//HEAD if missing. But it is not needed to always ask for remote HEAD. When we are fetching from a remote, for which we have remote-tracking branches, we do need to know about HEAD. But if we are doing one-shot fetch, e.g., $ git fetch --tags https://github.com/git/git we do not even know what sub-hierarchy of refs/remotes// we need to adjust the remote HEAD for. There is no need to ask for HEAD in such a case. Incidentally, because the unconditional request to list "HEAD" affected the number of ref-prefixes requested in the ls-remote request, this affected how the requests for tags are added to the same ls-remote request, breaking "git fetch --tags $URL" performed against a URL that is not configured as a remote. Reported-by: Josh Steadmon [jc: tests are also borrowed from Josh's patch] Signed-off-by: Junio C Hamano --- diff --git a/builtin/fetch.c b/builtin/fetch.c index a64de4485f..3eb6f3acc9 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -1643,6 +1643,21 @@ cleanup: return result; } +static int uses_remote_tracking(struct transport *transport, struct refspec *rs) +{ + if (!remote_is_configured(transport->remote, 0)) + return 0; + + if (!rs->nr) + rs = &transport->remote->fetch; + + for (int i = 0; i < rs->nr; i++) + if (rs->items[i].dst) + return 1; + + return 0; +} + static int do_fetch(struct transport *transport, struct refspec *rs, const struct fetch_config *config) @@ -1712,7 +1727,10 @@ static int do_fetch(struct transport *transport, "refs/tags/"); } - strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD"); + if (uses_remote_tracking(transport, rs)) { + must_list_refs = 1; + strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD"); + } if (must_list_refs) { trace2_region_enter("fetch", "remote_refs", the_repository); diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 87698341f5..d7602333ff 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -189,6 +189,23 @@ test_expect_success 'fetch --prune --tags with refspec prunes based on refspec' git rev-parse sometag ' +test_expect_success 'fetch --tags gets tags even without a configured remote' ' + REMOTE="$(pwd)/test_tag_1" && + git init test_tag_1 && + ( + cd test_tag_1 && + test_commit foo + ) && + git init test_tag_2 && + ( + cd test_tag_2 && + git fetch --tags "file://$REMOTE" && + echo "foo" >expect && + git tag >actual && + test_cmp expect actual + ) +' + test_expect_success REFFILES 'fetch --prune fails to delete branches' ' cd "$D" && git clone . prune-fail &&