Re: bug? in checkout with ambiguous refnames
From: Junio C Hamano <hidden>
Date: 2016-06-15 22:50:21
Uwe Kleine-König [off-list ref] writes:
So working copy and cache are at refs/tags/sgu/mxs-amba-uart, HEAD points to refs/heads/sgu/mxs-amba-uart
I somehow thought that we had an explicit logic to favor an exact branch
name for "git checkout $branch" even when refs/something-other-than-head/$branch
exists, while issuing the ambiguity warning.
Ahh, what this part of the code in builtin/checkout.c does is totally
wrong:
/* we can't end up being in (2) anymore, eat the argument */
argv++;
argc--;
new.name = arg;
if ((new.commit = lookup_commit_reference_gently(rev, 1))) {
setup_branch_path(&new);
if ((check_ref_format(new.path) == CHECK_REF_FORMAT_OK) &&
resolve_ref(new.path, rev, 1, NULL))
;
else
new.path = NULL;
parse_commit(new.commit);
source_tree = new.commit->tree;
} else
source_tree = parse_tree_indirect(rev);
It uses lookup_commit_reference_gently() that follows the usual
tags-then-heads preference order, but then uses setup_branch_path() to
prefix the raw name with "refs/heads", which is totally backwards.
It should do something like:
- use setup-branch-path to get refs/heads/$name
- check-ref-format and resolve it; if these fail, then we are detaching
head at rev;
- otherwise, if the result of the resolution is not the same as rev, what
we have in rev is incorrect (it was taken from the usual
tags-then-heads rule but "checkout $name" must favor local branches).
update the rev with the result of resolving refs/heads/$name
- parse new.commit out of rev. we are checking out the branch $name.