Skip to content

Commit fd4692f

Browse files
peffgitster
authored andcommitted
checkout: restrict @-expansions when finding branch
When we parse "git checkout $NAME", we try to interpret $NAME as a local branch-name. If it is, then we point HEAD to that branch. Otherwise, we detach the HEAD at whatever commit $NAME points to. We do the interpretation by calling strbuf_branchname(), and then blindly sticking "refs/heads/" on the front. This leads to nonsense results when expansions like "@{upstream}" or "@" point to something besides a local branch. We end up with a local branch name like "refs/heads/origin/master" or "refs/heads/HEAD". Normally this has no user-visible effect because those branches don't exist, and so we fallback to feeding the result to get_sha1(), which resolves them correctly. But as the new test in t3204 shows, there are corner cases where the effect is observable, and we check out the wrong local branch rather than detaching to the correct one. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7d5c960 commit fd4692f

File tree

2 files changed

+11
-1
lines changed

2 files changed

+11
-1
lines changed

builtin/checkout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ static void setup_branch_path(struct branch_info *branch)
452452
{
453453
struct strbuf buf = STRBUF_INIT;
454454

455-
strbuf_branchname(&buf, branch->name, 0);
455+
strbuf_branchname(&buf, branch->name, INTERPRET_BRANCH_LOCAL);
456456
if (strcmp(buf.buf, branch->name))
457457
branch->name = xstrdup(buf.buf);
458458
strbuf_splice(&buf, 0, 0, "refs/heads/", 11);

t/t3204-branch-name-interpretation.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,14 @@ test_expect_success 'delete branch named "@"' '
120120
expect_deleted refs/heads/@
121121
'
122122

123+
test_expect_success 'checkout does not treat remote @{upstream} as a branch' '
124+
git update-ref refs/remotes/origin/checkout one &&
125+
git branch --set-upstream-to=origin/checkout &&
126+
git update-ref refs/heads/origin/checkout two &&
127+
git update-ref refs/heads/remotes/origin/checkout two &&
128+
129+
git checkout @{upstream} &&
130+
expect_branch HEAD one
131+
'
132+
123133
test_done

0 commit comments

Comments
 (0)