On 2009.08.26 18:46:47 +0400, Kirill A. Korinskiy wrote:
quoted hunk ↗ jump to hunk
@@ -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 ;-)).
quoted hunk ↗ jump to hunk
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