Skip to content

Commit 6c915c3

Browse files
committed
fetch: do not ask for HEAD unnecessarily
In 3f763dd (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/<name>/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/<remote>/ 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 <[email protected]> [jc: tests are also borrowed from Josh's patch] Signed-off-by: Junio C Hamano <[email protected]>
1 parent e02082c commit 6c915c3

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

builtin/fetch.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1643,6 +1643,21 @@ static int set_head(const struct ref *remote_refs)
16431643
return result;
16441644
}
16451645

1646+
static int uses_remote_tracking(struct transport *transport, struct refspec *rs)
1647+
{
1648+
if (!remote_is_configured(transport->remote, 0))
1649+
return 0;
1650+
1651+
if (!rs->nr)
1652+
rs = &transport->remote->fetch;
1653+
1654+
for (int i = 0; i < rs->nr; i++)
1655+
if (rs->items[i].dst)
1656+
return 1;
1657+
1658+
return 0;
1659+
}
1660+
16461661
static int do_fetch(struct transport *transport,
16471662
struct refspec *rs,
16481663
const struct fetch_config *config)
@@ -1712,7 +1727,10 @@ static int do_fetch(struct transport *transport,
17121727
"refs/tags/");
17131728
}
17141729

1715-
strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
1730+
if (uses_remote_tracking(transport, rs)) {
1731+
must_list_refs = 1;
1732+
strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
1733+
}
17161734

17171735
if (must_list_refs) {
17181736
trace2_region_enter("fetch", "remote_refs", the_repository);

t/t5510-fetch.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,23 @@ test_expect_success 'fetch --prune --tags with refspec prunes based on refspec'
189189
git rev-parse sometag
190190
'
191191

192+
test_expect_success 'fetch --tags gets tags even without a configured remote' '
193+
REMOTE="$(pwd)/test_tag_1" &&
194+
git init test_tag_1 &&
195+
(
196+
cd test_tag_1 &&
197+
test_commit foo
198+
) &&
199+
git init test_tag_2 &&
200+
(
201+
cd test_tag_2 &&
202+
git fetch --tags "file://$REMOTE" &&
203+
echo "foo" >expect &&
204+
git tag >actual &&
205+
test_cmp expect actual
206+
)
207+
'
208+
192209
test_expect_success REFFILES 'fetch --prune fails to delete branches' '
193210
cd "$D" &&
194211
git clone . prune-fail &&

0 commit comments

Comments
 (0)