Skip to content

Commit c1921c1

Browse files
peffgitster
authored andcommitted
clone: always fetch remote HEAD
In most cases, fetching the remote HEAD explicitly is unnecessary. It's just a symref pointing to a branch which we are already fetching, so we will already ask for its sha1. However, if the remote has a detached HEAD, things are less certain. We do not ask for HEAD's sha1, but we do try to write it into a local detached HEAD. In most cases this is fine, as the remote HEAD is pointing to some part of the history graph that we will fetch via the refs. But if the remote HEAD points to an "orphan" commit (one which was is not an ancestor of any refs), then we will not have the object, and update_ref will complain when we try to write the detached HEAD, aborting the whole clone. This patch makes clone always explicitly ask the remote for the sha1 of its HEAD commit. In the non-detached case, this is a no-op, as we were going to ask for that sha1 anyway. In the regular detached case, this will add an extra "want" to the protocol negotiation, but will not change the history that gets sent. And in the detached orphan case, we will fetch the orphaned history so that we can write it into our local detached HEAD. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 59a5775 commit c1921c1

File tree

2 files changed

+10
-6
lines changed

2 files changed

+10
-6
lines changed

builtin/clone.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -340,8 +340,9 @@ static void remove_junk_on_signal(int signo)
340340
static struct ref *wanted_peer_refs(const struct ref *refs,
341341
struct refspec *refspec)
342342
{
343-
struct ref *local_refs = NULL;
344-
struct ref **tail = &local_refs;
343+
struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
344+
struct ref *local_refs = head;
345+
struct ref **tail = head ? &head->next : &local_refs;
345346

346347
get_fetch_map(refs, refspec, &tail, 0);
347348
if (!option_mirror)
@@ -354,8 +355,11 @@ static void write_remote_refs(const struct ref *local_refs)
354355
{
355356
const struct ref *r;
356357

357-
for (r = local_refs; r; r = r->next)
358+
for (r = local_refs; r; r = r->next) {
359+
if (!r->peer_ref)
360+
continue;
358361
add_extra_ref(r->peer_ref->name, r->old_sha1, 0);
362+
}
359363

360364
pack_refs(PACK_REFS_ALL);
361365
clear_extra_refs();

t/t5707-clone-detached.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,18 @@ test_expect_success 'cloned HEAD is detached' '
5858
head_is_detached detached-history
5959
'
6060

61-
test_expect_failure 'clone repo (orphan detached HEAD)' '
61+
test_expect_success 'clone repo (orphan detached HEAD)' '
6262
git checkout master^0 &&
6363
echo four >file &&
6464
git commit -a -m four &&
6565
git clone "file://$PWD" detached-orphan
6666
'
67-
test_expect_failure 'cloned HEAD matches' '
67+
test_expect_success 'cloned HEAD matches' '
6868
echo four >expect &&
6969
git --git-dir=detached-orphan/.git log -1 --format=%s >actual &&
7070
test_cmp expect actual
7171
'
72-
test_expect_failure 'cloned HEAD is detached' '
72+
test_expect_success 'cloned HEAD is detached' '
7373
head_is_detached detached-orphan
7474
'
7575

0 commit comments

Comments
 (0)