From: Nguyễn Thái Ngọc Duy Date: Fri, 13 Jan 2012 07:22:01 GMT Subject: [PATCH v4 09/10] clone: allow --branch to take a tag Message-ID: <1326439322-15648-10-git-send-email-pclouds@gmail.com> In-Reply-To: <1326189427-20800-1-git-send-email-pclouds@gmail.com> Because a tag ref cannot be put to HEAD, HEAD will become detached. This is consistent with "git checkout ". 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 --- Documentation/git-clone.txt | 5 +++-- builtin/clone.c | 13 +++++++++++++ t/t5601-clone.sh | 9 +++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 4b8b26b..db2b29c 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -146,8 +146,9 @@ objects from the source repository into a pack in the cloned repository. -b :: Instead of pointing the newly created HEAD to the branch pointed to by the cloned repository's HEAD, point to `` branch - instead. In a non-bare repository, this is the branch that will - be checked out. + instead. `--branch` can also take tags and treat them like + detached HEAD. In a non-bare repository, this is the branch + that will be checked out. --upload-pack :: -u :: diff --git a/builtin/clone.c b/builtin/clone.c index 6a2886a..a3c8f78 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -471,6 +471,11 @@ static void update_head(const struct ref *our, const struct ref *remote, update_ref(msg, "HEAD", our->old_sha1, NULL, 0, DIE_ON_ERR); install_branch_config(0, head, option_origin, our->name); } + } else if (our) { + struct commit *c = lookup_commit_reference(our->old_sha1); + /* --branch specifies a non-branch (i.e. tags), detach HEAD */ + update_ref(msg, "HEAD", c->object.sha1, + NULL, REF_NODEREF, DIE_ON_ERR); } else if (remote) { /* * We know remote HEAD points to a non-branch, or @@ -770,6 +775,14 @@ int cmd_clone(int argc, const char **argv, const char *prefix) find_ref_by_name(mapped_refs, head.buf); strbuf_release(&head); + if (!our_head_points_at) { + strbuf_addstr(&head, "refs/tags/"); + strbuf_addstr(&head, option_branch); + our_head_points_at = + find_ref_by_name(mapped_refs, head.buf); + strbuf_release(&head); + } + if (!our_head_points_at) die(_("Remote branch %s not found in " "upstream %s, using HEAD instead"), diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index e0b8db6..67869b4 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -271,4 +271,13 @@ test_expect_success 'clone from original with relative alternate' ' grep /src/\\.git/objects target-10/objects/info/alternates ' +test_expect_success 'clone checking out a tag' ' + git clone --branch=some-tag src dst.tag && + GIT_DIR=src/.git git rev-parse some-tag >expected && + test_cmp expected dst.tag/.git/HEAD && + GIT_DIR=dst.tag/.git git config remote.origin.fetch >fetch.actual && + echo "+refs/heads/*:refs/remotes/origin/*" >fetch.expected && + test_cmp fetch.expected fetch.actual +' + test_done -- 1.7.3.1.256.g2539c.dirty