Which characters are illegal within a branch name?

Which characters are illegal within a branch name?


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.


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 'Ω'