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/<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 <steadmon@google.com>
[jc: tests are also borrowed from Josh's patch]
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
parent
e02082c7f8
commit
6c915c3f85
|
@ -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);
|
||||
|
|
|
@ -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 &&
|
||||
|
|
Loading…
Reference in New Issue