The good news is, with Git 2.16 (Q1 2018), that issue won't come up easily anymore, since "git branch
" and "git checkout -b
" are now forbidden from creating a branch whose name is "HEAD".
See commit 662a4c8 (14 Nov 2017) by Kaartic Sivaraam (sivaraam
).
See commit a625b09 (14 Nov 2017), and commit bc1c9c0, commit 8280c4c (13 Oct 2017) by Junio C Hamano (gitster
).
(Merged by Junio C Hamano -- gitster
-- in commit 1616928, 28 Nov 2017)
branch
: correctly reject refs/heads/{-dash,HEAD}
strbuf_check_branch_ref()
is the central place where many codepaths
see if a proposed name is suitable for the name of a branch.
It was designed to allow us to get stricter than the check_refname_format()
check used for refnames in general, and we already use it to reject a branch whose name begins with a '-
'.
The function gets a strbuf
and a string "name
", and returns non-zero if the name is not appropriate as the name for a branch.
When the name is good, it places the full refname for the branch with the proposed name in the strbuf
before it returns.
However, it turns out that one caller looks at what is in the strbuf
even when the function returns an error.
Make the function populate the strbuf
even when it returns an error.
That way, when "-dash
" is given as name, "refs/heads/-dash
" is placed in the strbuf
when returning an error to copy_or_rename_branch()
, which notices that the user is trying to recover with "git branch -m -- -dash dash
" to
rename "-dash
" to "dash
".
While at it, use the same mechanism to also reject "HEAD
" as a branch name.
Even if you tried to "cheat", and use git symbolic-ref
to point HEAD
to a nonsensical ref (like 'HEAD
'!), that would not work with Git 2.38 (Q3 2022):
"git symbolic-ref symref non..sen..se
"(man) is now diagnosed as an error.
See commit 04ede97 (01 Aug 2022) by Linus Torvalds (torvalds
).
(Merged by Junio C Hamano -- gitster
-- in commit 8faaf69, 12 Aug 2022)
symbolic-ref
: refuse to set syntactically invalid target
Signed-off-by: Linus Torvalds
Signed-off-by: Jeff King
You can feed absolute garbage to symbolic-ref as a target like:
git symbolic-ref HEAD refs/heads/foo..bar
While this doesn't technically break the repo entirely (our "is it a Git directory detector looks only for refs/
at the start), we would never resolve such a ref, as the "..
" is invalid within a refname.
Let's flag these as invalid at creation time to help the caller realize that what they're asking for is bogus.
A few notes:
We use REFNAME_ALLOW_ONELEVEL
here, which lets:
git update-ref refs/heads/foo FETCH_HEAD
continue to work.
It's unclear whether anybody wants to do something
so odd, but it does work now, so this is erring on the conservative side.
We need to keep our HEAD-specific check for "does it start with refs/".
The ALLOW_ONELEVEL
flag means we won't be enforcing that for other refs, but HEAD is special here because of the checks in validate_headref()
.
You would get the error message:
Refusing to set 'HEAD' to invalid ref 'xxx'