Re: [PATCH] Add option -b/--branch to clone for select a new HEAD
- From
Björn Steinbrink <b.steinbrink@gmx.de>
- Date
- Aug 26, 2009, 15:50 UTC
- Message-ID
- <20090826155029.GA5750@atjola.homenet>
- In-Reply-To
- <1251298007-18693-1-git-send-email-catap@catap.ru>
On 2009.08.26 18:46:47 +0400, Kirill A. Korinskiy wrote:
Show 22 quoted lines
> @@ -518,8 +521,22 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>
> mapped_refs = write_remote_refs(refs, refspec, reflog_msg.buf);
>
> - remote_head = find_ref_by_name(refs, "HEAD");
> - head_points_at = guess_remote_head(remote_head, mapped_refs, 0);
> + if (option_branch) {
> + strbuf_addf(&branch_head, "%s%s", src_ref_prefix, option_branch);
> +
> + remote_head = find_ref_by_name(refs, branch_head.buf);
> + }
> +
> + if (!remote_head) {
> + if (option_branch)
> + warning("Remote branch %s not found in upstream %s"
> + ", using HEAD instead",
> + option_branch, option_origin);
> +
> + remote_head = find_ref_by_name(refs, "HEAD");
> + }
> +
> + head_points_at = guess_remote_head(remote_head, mapped_refs, 1);Just setting "all" to 1 there is wrong. With "all" set to 1, guess_remote_head() returns a linked list of _all_ matching refs. The first entry in that list depends on the order of mapped_refs.
doener@atjola:h $ mkdir a; cd a; git init Initialized empty Git repository in /home/doener/h/a/.git/ doener@atjola:a (master) $ git commit --allow-empty -m init [master (root-commit) aa39247] init doener@atjola:a (master) $ git branch foo doener@atjola:a (master) $ cd ..
doener@atjola:h $ (git clone -b foo a foo; cd foo; git branch) Initialized empty Git repository in /home/doener/h/foo/.git/ * foo
doener@atjola:h $ (git clone -b master a master; cd master; git branch) Initialized empty Git repository in /home/doener/h/master/.git/ * foo
Here, "foo" was first in mapped_refs, and so "-b master" used that, too.
Using guess_remote_head() seems pretty wrong. With -b given, you don't want to guess anymore, you _know_ which one you want. Unfortunately, I don't see a straight-forward way to handle that (but I'm totally clueless about the code, so don't let me scare you ;-)).
Show 51 quoted lines
> diff --git a/t/t5706-clone-branch.sh b/t/t5706-clone-branch.sh > new file mode 100755 > index 0000000..b5fec50 > --- /dev/null > +++ b/t/t5706-clone-branch.sh > @@ -0,0 +1,49 @@ > +#!/bin/sh > + > +test_description='branch clone options' > +. ./test-lib.sh > + > +test_expect_success 'setup' ' > + > + mkdir parent && > + (cd parent && git init && > + echo one >file && git add file && > + git commit -m one && git branch foo && > + git checkout -b two && > + echo two >f && git add f && git commit -m two && > + git checkout master) > + > +' > + > +test_expect_success 'clone' ' > + > + git clone parent clone && > + (cd clone && > + test $(git rev-parse --verify HEAD) = \ > + $(git rev-parse --verify refs/remotes/origin/master) && > + test $(git rev-parse --verify HEAD) != \ > + $(git rev-parse --verify refs/remotes/origin/two)) > + > + > +' > + > +test_expect_success 'clone -b two' ' > + > + git clone -b two parent clone-b && > + (cd clone-b && > + test $(git rev-parse --verify HEAD) = \ > + $(git rev-parse --verify refs/remotes/origin/two) && > + test $(git rev-parse --verify HEAD) != \ > + $(git rev-parse --verify refs/remotes/origin/master)) > + > +' > + > +test_expect_success 'clone -b foo' ' > + > + git clone -b foo parent clone-b-foo && > + (cd clone-b-foo && > + test $(git branch | grep \* | sed -e s:\*\ ::) = foo)
This should probably do "git symbolic-ref HEAD" instead of the branch + grep + sed. And it should also verify that rev-parse foo == rev-parse origin/foo.
And to catch the above bug, you need a second test like that, but for "master" instead of "foo".
HTH Björn