347

Which characters are illegal within a branch name?

ThinkingStiff
  • 64,767
  • 30
  • 146
  • 239
lunohodov
  • 5,179
  • 2
  • 25
  • 17
  • 2
    According to the thread https://stackoverflow.com/questions/16862933/how-to-resolve-gits-not-something-we-can-merge-error, a "," comma is also illegal. – pbuerki Jul 27 '17 at 19:02

5 Answers5

401

Naming rules for refname:

Git imposes the following rules on how references are named:

  1. They can include slash / for hierarchical (directory) grouping, but no slash-separated component can begin with a dot . or end with the sequence .lock.

  2. They must contain at least one /. This enforces the presence of a category like heads/, tags/ etc. but the actual names are not restricted. If the --allow-onelevel option is used, this rule is waived.

  3. They cannot have two consecutive dots .. anywhere.

  4. They cannot have ASCII control characters (i.e. bytes whose values are lower than \040, or \177 DEL), space, tilde ~, caret ^, or colon : anywhere.

  5. They cannot have question-mark ?, asterisk *, or open bracket [ anywhere. See the --refspec-pattern option below for an exception to this rule.

  6. They cannot begin or end with a slash / or contain multiple consecutive slashes (see the --normalize option below for an exception to this rule)

  7. They cannot end with a dot .

  8. They cannot contain a sequence @{.

  9. They cannot be the single character @.

  10. They cannot contain a \.

On top of that, additional rule for branch name:

  1. They cannot start with a dash -

Thanks to Jakub Narębski, the man page for git check-ref-format has more details.

Mike Frysinger
  • 2,827
  • 1
  • 21
  • 26
Manoj Govindan
  • 72,339
  • 21
  • 134
  • 141
  • 13
    Worth mentioning that '>' is allowed, but to switch to that branch in bash it requires escaping with a preceding '\' – igniteflow Oct 25 '13 at 12:46
  • Ive had problems using a comma in branch names, but don't see that as being listed as not allowed on the man page. anyone know for sure? – DMTintner Apr 01 '14 at 13:06
  • 10
    I'm confused about rule #2 in the **man page** you linked. It says *"2. They must contain at least one `/`."* Please explain? None of my branches have a `/` in the name. – chharvey Jul 10 '14 at 02:56
  • 16
    @chharvey: a “branch” without a `/` has `heads/` prepended to it “automatically”. Actually: without a `/`, it is not clear yet if it’s a branch or a tag or something else... – Robert Siemer Feb 25 '15 at 14:14
  • 1
    @DMTintner: Commas are allowed. – Robert Siemer Feb 25 '15 at 14:16
  • 1
    There also appear to be some characters that cause errors on Windows but are valid on Mac/Linux, such as `"`, this has sometimes caused problems for us; if such a branch is pushed, it must be renamed on or deleted from the master repository before Windows users are able to fetch again. Alternatively, it might be an egit or jgit bug on Windows, if git itself supports quotes in branch names on Windows. – Theodore Murdock May 27 '16 at 19:53
  • 1
    For the sake of sanity, brevity, predictability (and portability: for scripts regex'ing on branch names), I _only_ use dash ("`-`"), lowercase (`[a-z]`) & numbers (`[0-9]`) in branch names. No underscores ("`_`"), nor uppercase. Why make it more complicated than necessary? More controversially, I also never use slash ("`/`"), because it's a useful indication the branch is "special". And basically there's no reason to use a "`/`" instead of a "`-`", except to aid dumb gui tools that automatically fold them close (eg a tree), which a smart gui could/should just as easily do on dashes "`-`". – michael Nov 01 '16 at 10:01
  • 6
    here is a regular expression for this /^[\./]|\.\.|@{|[\/\.]$|^@$|[~^:\x00-\x20\x7F\s?*[\\\]/g this will find the invalid characters so you can replace them with a '-' or whatever character you want – Tony Brix Feb 21 '17 at 18:59
  • 4
    It's also worth noting the `&` character can sometimes cause issues in branch names on Windows – Stevoisiak Apr 13 '17 at 15:22
  • 1
    @michael I second the bottom line: **"Why make it more complicated than necessary?"** This means to simply exclude all characters which could conceivably cause trouble on any machine or with any tool, or in other words restrict oneself to a minimalist but sufficient whitelist. – Peter - Reinstate Monica Jul 07 '17 at 08:41
  • So I can have `git checkout -b mybranch.1.2`? – Si8 Dec 08 '17 at 19:41
  • I wonder if semicolon is not allowed?, we have used semicolon, and then I used git push --mirror to clone our repository to another server, and every branch name with semicolon failed. It used the first part, and the next part it tried to execute as an command: remote: fatal: ambiguous argument 'refs/heads/BUG-199': unknown revision or path not in the working tree. remote: Use '--' to separate paths from revisions, like this: remote: 'git [...] -- [...]' remote: sh: QueryBuilder: command not found for branch called BUG-199;QueryBuilder. – neslekkiM Dec 19 '17 at 10:10
  • 2
    @neslekkiM a semicolon may be interpreted by bash as a new instruction... Have you tried escaping it like `\;`? – CPHPython Sep 18 '19 at 10:59
  • @CPHPython I was thinking about something like that, but it when running the convert tool, it should escape things, it looked like it faulted on the serverside, because it did not fail locally when testing here.But we ended up deleting all branches and migrated. – neslekkiM Sep 19 '19 at 11:08
  • 1
    Using git check-ref-format --branch worked for me to determine whether the branch was in a valid format. – Daniel Eagle Dec 02 '19 at 18:20
  • accented letters are allowed? – Israel Perales Mar 13 '20 at 00:06
  • 1
    There's another restriction that I don't see listed explicitly. Both `one/two` and `one/two/three` are valid branch names, but you can't have both in the same repo. Because branches are represented as files under `.git/refs/heads`, and `/` characters in branch names create subdirectories, `one/two` can't be both a directory and a file. Also, if you're on a case-insensitive file system, `foo` and `FOO` are treated as the same. – Keith Thompson Jun 16 '21 at 21:38
  • The list of illegal characters is not complete -> and => aren't permitted, and unicode names cause other issues. The branch code should allow any unicode names and the tooling should likewise. – ggb667 Feb 28 '22 at 13:59
  • Like @keith-thompson said, if one already has a branch named `XXX`, then a new branch to be named `XXX/YYY` will not be permitted. The error message would be something like: `fatal: cannot lock ref 'refs/heads/XXX/YYY': 'refs/heads/XXX' exists; cannot create 'refs/heads/XXX/YYY'`. – Kevin Dec 20 '22 at 04:03
  • I have branches like 'dev' 'hotfix' ... and I want to create a branch with a name as 'dev/response_handle' . When I tried this I am getting invalid branch name exception . Anything that I am missing ? – Hari Krishnan Ramachandran Mar 02 '23 at 05:01
11

The accepted answer and the man page already explain which rules apply to Git branch names.

In the Git source code, the refname_disposition array is used to determine how to handle various characters in refnames. The indexes in the array correspond to ASCII codes and the values indicate how the ASCII characters are handled.

/*
 * How to handle various characters in refnames:
 * 0: An acceptable character for refs
 * 1: End-of-component
 * 2: ., look for a preceding . to reject .. in refs
 * 3: {, look for a preceding @ to reject @{ in refs
 * 4: A bad character: ASCII control characters, and
 *    ":", "?", "[", "\", "^", "~", SP, or TAB
 * 5: *, reject unless REFNAME_REFSPEC_PATTERN is set
 */
static unsigned char refname_disposition[256] = {
    1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 1,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
};

Since 4 means that the corresponding ASCII character is not allowed inside branch names, there are 39 disallowed characters. The disallowed characters are ASCII control characters (ASCII codes < 32), the printable characters : ? [ \ ^ ~ and the whitespace/tab character.

3 more characters require some conditions to be met (see doc comment):

  • .: Two subsequent dots are forbidden.
  • {: The substring @{ is forbidden.
  • *: Reject unless REFNAME_REFSPEC_PATTERN is set.

The null byte terminates the branch name and / creates a new directory hierarchy for the branch. Therefore, branch names cannot end with a slash. For example git checkout -b 'a/b/c' will create the corresponding directory structure under .git/refs/heads

Note that UTF-8 characters can be used in branch names:

$ git checkout -b $'\xCE\xA9'
Switched to a new branch 'Ω'
upe
  • 1,862
  • 1
  • 19
  • 33
3

As an addition, care must be taken if you consider to use the dollar sign $ character.

git branch pew$ign will create pew.

In order to create a branch that has $ within it the whole name should be wrapped in quotes that make it a string literal: git branch 'pew$ign'. Ideally you should avoid to use the symbol whatsoever.

Aaron Blenkush
  • 3,034
  • 2
  • 28
  • 54
daGo
  • 2,584
  • 26
  • 24
  • 8
    This is not specific to Git-- it's part of how POSIX shells process commands. When you don't have quotes (or a preceding backslash), $ign is interpreted as an empty shell variable, so git only sees 'pew'. – Aaron Bentley Feb 16 '22 at 04:25
1

To complete the main answer by Manoj Govindan :

  • @ is a valid branch name (on git version git version 2.24.3 (Apple Git-128))
  • HEAD is not a valid branch name (by captain obvious!)
  • length is limited (by the OS, on Mac OS 10.15.7, 250 characters is the maximum, either ascii or not-ascii)
lavalade
  • 329
  • 2
  • 11
0

It doesn't like > or ==> or ->

ggb667
  • 1,881
  • 2
  • 20
  • 44
  • 4
    Of my knowledge `>`, `==>` and `->` are valid branch names. Problems during branch creation can occur when [special characters (like `>`) are not escaped properly](https://stackoverflow.com/q/15783701). Wrapping the branch names in quotes should work, e.g. `git checkout -b ">==>->"`. – upe Apr 23 '22 at 09:40