Skip to content

Commit 8ab19bc

Browse files
committed
Merge branch 'jk/clone-detached'
* jk/clone-detached: clone: always fetch remote HEAD make copy_ref globally available consider only branches in guess_remote_head t: add tests for cloning remotes with detached HEAD
2 parents b04f826 + c1921c1 commit 8ab19bc

File tree

4 files changed

+88
-6
lines changed

4 files changed

+88
-6
lines changed

builtin/clone.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,9 @@ static void remove_junk_on_signal(int signo)
345345
static struct ref *wanted_peer_refs(const struct ref *refs,
346346
struct refspec *refspec)
347347
{
348-
struct ref *local_refs = NULL;
349-
struct ref **tail = &local_refs;
348+
struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
349+
struct ref *local_refs = head;
350+
struct ref **tail = head ? &head->next : &local_refs;
350351

351352
get_fetch_map(refs, refspec, &tail, 0);
352353
if (!option_mirror)
@@ -359,8 +360,11 @@ static void write_remote_refs(const struct ref *local_refs)
359360
{
360361
const struct ref *r;
361362

362-
for (r = local_refs; r; r = r->next)
363+
for (r = local_refs; r; r = r->next) {
364+
if (!r->peer_ref)
365+
continue;
363366
add_extra_ref(r->peer_ref->name, r->old_sha1, 0);
367+
}
364368

365369
pack_refs(PACK_REFS_ALL);
366370
clear_extra_refs();

remote.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -896,7 +896,7 @@ struct ref *alloc_ref(const char *name)
896896
return alloc_ref_with_prefix("", 0, name);
897897
}
898898

899-
static struct ref *copy_ref(const struct ref *ref)
899+
struct ref *copy_ref(const struct ref *ref)
900900
{
901901
struct ref *cpy;
902902
size_t len;
@@ -1667,7 +1667,9 @@ struct ref *guess_remote_head(const struct ref *head,
16671667

16681668
/* Look for another ref that points there */
16691669
for (r = refs; r; r = r->next) {
1670-
if (r != head && !hashcmp(r->old_sha1, head->old_sha1)) {
1670+
if (r != head &&
1671+
!prefixcmp(r->name, "refs/heads/") &&
1672+
!hashcmp(r->old_sha1, head->old_sha1)) {
16711673
*tail = copy_ref(r);
16721674
tail = &((*tail)->next);
16731675
if (!all)

remote.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ struct refspec {
7070
extern const struct refspec *tag_refspec;
7171

7272
struct ref *alloc_ref(const char *name);
73-
73+
struct ref *copy_ref(const struct ref *ref);
7474
struct ref *copy_ref_list(const struct ref *ref);
7575

7676
int check_ref_type(const struct ref *ref, int flags);

t/t5707-clone-detached.sh

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#!/bin/sh
2+
3+
test_description='test cloning a repository with detached HEAD'
4+
. ./test-lib.sh
5+
6+
head_is_detached() {
7+
git --git-dir=$1/.git rev-parse --verify HEAD &&
8+
test_must_fail git --git-dir=$1/.git symbolic-ref HEAD
9+
}
10+
11+
test_expect_success 'setup' '
12+
echo one >file &&
13+
git add file &&
14+
git commit -m one &&
15+
echo two >file &&
16+
git commit -a -m two &&
17+
git tag two &&
18+
echo three >file &&
19+
git commit -a -m three
20+
'
21+
22+
test_expect_success 'clone repo (detached HEAD points to branch)' '
23+
git checkout master^0 &&
24+
git clone "file://$PWD" detached-branch
25+
'
26+
test_expect_success 'cloned HEAD matches' '
27+
echo three >expect &&
28+
git --git-dir=detached-branch/.git log -1 --format=%s >actual &&
29+
test_cmp expect actual
30+
'
31+
test_expect_failure 'cloned HEAD is detached' '
32+
head_is_detached detached-branch
33+
'
34+
35+
test_expect_success 'clone repo (detached HEAD points to tag)' '
36+
git checkout two^0 &&
37+
git clone "file://$PWD" detached-tag
38+
'
39+
test_expect_success 'cloned HEAD matches' '
40+
echo two >expect &&
41+
git --git-dir=detached-tag/.git log -1 --format=%s >actual &&
42+
test_cmp expect actual
43+
'
44+
test_expect_success 'cloned HEAD is detached' '
45+
head_is_detached detached-tag
46+
'
47+
48+
test_expect_success 'clone repo (detached HEAD points to history)' '
49+
git checkout two^ &&
50+
git clone "file://$PWD" detached-history
51+
'
52+
test_expect_success 'cloned HEAD matches' '
53+
echo one >expect &&
54+
git --git-dir=detached-history/.git log -1 --format=%s >actual &&
55+
test_cmp expect actual
56+
'
57+
test_expect_success 'cloned HEAD is detached' '
58+
head_is_detached detached-history
59+
'
60+
61+
test_expect_success 'clone repo (orphan detached HEAD)' '
62+
git checkout master^0 &&
63+
echo four >file &&
64+
git commit -a -m four &&
65+
git clone "file://$PWD" detached-orphan
66+
'
67+
test_expect_success 'cloned HEAD matches' '
68+
echo four >expect &&
69+
git --git-dir=detached-orphan/.git log -1 --format=%s >actual &&
70+
test_cmp expect actual
71+
'
72+
test_expect_success 'cloned HEAD is detached' '
73+
head_is_detached detached-orphan
74+
'
75+
76+
test_done

0 commit comments

Comments
 (0)