Skip to content

Commit 5a7d5b6

Browse files
pcloudsgitster
authored andcommittedJan 17, 2012
clone: allow --branch to take a tag
Because a tag ref cannot be put to HEAD, HEAD will become detached. This is consistent with "git checkout <tag>". This is mostly useful in shallow clone, where it allows you to clone a tag in addtion to branches. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 920b691 commit 5a7d5b6

File tree

4 files changed

+46
-3
lines changed

4 files changed

+46
-3
lines changed
 

‎Documentation/git-clone.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,9 @@ objects from the source repository into a pack in the cloned repository.
147147
-b <name>::
148148
Instead of pointing the newly created HEAD to the branch pointed
149149
to by the cloned repository's HEAD, point to `<name>` branch
150-
instead. In a non-bare repository, this is the branch that will
151-
be checked out.
150+
instead. `--branch` can also take tags and treat them like
151+
detached HEAD. In a non-bare repository, this is the branch
152+
that will be checked out.
152153

153154
--upload-pack <upload-pack>::
154155
-u <upload-pack>::

‎builtin/clone.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,15 @@ static struct ref *find_remote_branch(const struct ref *refs, const char *branch
420420
strbuf_addstr(&head, branch);
421421
ref = find_ref_by_name(refs, head.buf);
422422
strbuf_release(&head);
423+
424+
if (ref)
425+
return ref;
426+
427+
strbuf_addstr(&head, "refs/tags/");
428+
strbuf_addstr(&head, branch);
429+
ref = find_ref_by_name(refs, head.buf);
430+
strbuf_release(&head);
431+
423432
return ref;
424433
}
425434

@@ -441,8 +450,12 @@ static struct ref *wanted_peer_refs(const struct ref *refs,
441450
if (!remote_head && option_branch)
442451
warning(_("Could not find remote branch %s to clone."),
443452
option_branch);
444-
else
453+
else {
445454
get_fetch_map(remote_head, refspec, &tail, 0);
455+
456+
/* if --branch=tag, pull the requested tag explicitly */
457+
get_fetch_map(remote_head, tag_refspec, &tail, 0);
458+
}
446459
} else
447460
get_fetch_map(refs, refspec, &tail, 0);
448461

@@ -515,6 +528,11 @@ static void update_head(const struct ref *our, const struct ref *remote,
515528
update_ref(msg, "HEAD", our->old_sha1, NULL, 0, DIE_ON_ERR);
516529
install_branch_config(0, head, option_origin, our->name);
517530
}
531+
} else if (our) {
532+
struct commit *c = lookup_commit_reference(our->old_sha1);
533+
/* --branch specifies a non-branch (i.e. tags), detach HEAD */
534+
update_ref(msg, "HEAD", c->object.sha1,
535+
NULL, REF_NODEREF, DIE_ON_ERR);
518536
} else if (remote) {
519537
/*
520538
* We know remote HEAD points to a non-branch, or

‎t/t5500-fetch-pack.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,4 +311,19 @@ EOF
311311
test_cmp count6.expected count6.actual
312312
'
313313

314+
test_expect_success 'shallow cloning single tag' '
315+
git clone --depth 1 --branch=TAGB1 "file://$(pwd)/." shallow7 &&
316+
cat >taglist.expected <<\EOF &&
317+
TAGB1
318+
TAGB2
319+
EOF
320+
GIT_DIR=shallow7/.git git tag -l >taglist.actual &&
321+
test_cmp taglist.expected taglist.actual &&
322+
323+
echo "in-pack: 7" > count7.expected &&
324+
GIT_DIR=shallow7/.git git count-objects -v |
325+
grep "^in-pack" > count7.actual &&
326+
test_cmp count7.expected count7.actual
327+
'
328+
314329
test_done

‎t/t5601-clone.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,4 +271,13 @@ test_expect_success 'clone from original with relative alternate' '
271271
grep /src/\\.git/objects target-10/objects/info/alternates
272272
'
273273

274+
test_expect_success 'clone checking out a tag' '
275+
git clone --branch=some-tag src dst.tag &&
276+
GIT_DIR=src/.git git rev-parse some-tag >expected &&
277+
test_cmp expected dst.tag/.git/HEAD &&
278+
GIT_DIR=dst.tag/.git git config remote.origin.fetch >fetch.actual &&
279+
echo "+refs/heads/*:refs/remotes/origin/*" >fetch.expected &&
280+
test_cmp fetch.expected fetch.actual
281+
'
282+
274283
test_done

0 commit comments

Comments
 (0)
Please sign in to comment.