path: root/sha1_name.c
diff options
authorJunio C Hamano <>2017-11-14 11:42:58 (GMT)
committerJunio C Hamano <>2017-11-15 02:41:53 (GMT)
commita625b092cc59940521789fe8a3ff69c8d6b14eb2 (patch)
tree3df0f71f1729090dd80b2b4e80e8c95e8a691410 /sha1_name.c
parentbc1c9c0e674bdd293c29ae84365915848ed01d7a (diff)
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. Helped-by: Jeff King <> Helped-by: Kaartic Sivaraam <> Signed-off-by: Junio C Hamano <>
Diffstat (limited to 'sha1_name.c')
1 files changed, 12 insertions, 2 deletions
diff --git a/sha1_name.c b/sha1_name.c
index c7c5ab3..67961d6 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -1332,9 +1332,19 @@ void strbuf_branchname(struct strbuf *sb, const char *name, unsigned allowed)
int strbuf_check_branch_ref(struct strbuf *sb, const char *name)
strbuf_branchname(sb, name, INTERPRET_BRANCH_LOCAL);
- if (name[0] == '-')
- return -1;
+ /*
+ * This splice must be done even if we end up rejecting the
+ * name; builtin/branch.c::copy_or_rename_branch() still wants
+ * to see what the name expanded to so that "branch -m" can be
+ * used as a tool to correct earlier mistakes.
+ */
strbuf_splice(sb, 0, 0, "refs/heads/", 11);
+ if (*name == '-' ||
+ !strcmp(sb->buf, "refs/heads/HEAD"))
+ return -1;
return check_refname_format(sb->buf, 0);