Ridiculous Refs

October 19, 2019  |  2 minutes to read

How many different special characters can you jam into a Git ref name (i.e. the full name of a tag or a branch) before Git will complain?

The git logo with a exploding head inside
As if Git isn't complicated enough without testing its limits.

The answer is… a lot.

Here’s a list of ref names that Git considers valid, ranging from pedestrian to ludicrous:

  1. a/b
  2. A/B
  3. a/b/c/d
  4. a/b.c
  5. 0/1/2
  6. !/"#%&'{}+,-.<>;=@]_`{|}
  7. 🙂🚀😂🇺🇸💩🇨🇦💯👍❤️/🤦
  8. (╯°□°)/╯︵┻━┻
  9. ¯|_(ツ)_/¯

The opposite is a little less flashy, but equally useful. All of these are invalid ref names:

  1. a: At least one / is required
  2. a/.b: Slash-separated components can’t begin with a .
  3. a/b.: No ending with a .
  4. a/.lock: No ending with .lock
  5. a/b..c: Consecutive dots (..) are not allowed
  6. a/~^:?*[\: None of the characters after a/ are allowed
  7. a/b/: No ending with a slash
  8. /a/b: No beginning with a slash
  9. a/b//c: No consecutive slashes
  10. a/@{: The @{ sequence is not allowed

There’s some nuance to this second list - some of these rules can be relaxed in special situations. For the complete specification, check out the documentation for the check-ref-format command.

Wait, I’ve created lots of branches and tags that don’t contain a /!

Right! When you create a branch named my-feature, Git actually creates a ref named refs/heads/my-feature.

This is a bit of a tangent, but what Git is actually doing under the hood is creating a new file named my-feature inside your repo’s .git directory at .git/refs/heads/my-feature. You can see this for yourself by opening up .git/refs/heads in a file explorer. Understanding this makes it more obvious why the / character is required.

Why should I care about this?

If all you do with Git is pull, commit, push, and maybe the occasional rebase, you can ignore these edge cases. Just keep using nice, simple, boring names like my-feature-branch or v1.2.

However, if you’re building a tool that interacts with Git refs, you might want to throw a few of the crazier names listed above into your test cases.

In fact, this was my motivation for compiling these lists. I built a new GitLab Issue search feature that involved Git tag names, and I needed to make sure it handled any tag name the user threw at it. I was hoping to find something like the Big List of Naughty Strings for Git refs, but I couldn’t find anything beyond Git’s technical documentation.

Your list is wrong!

I wouldn’t be surprised! Please let me know by opening an issue!


The “exploding head” icon was created by Anniken & Andreas from the Noun Project.

Other posts you may enjoy:

Wordle Bot

January 25, 2022  |  6 minutes to read

Herding Gits

August 26, 2021  |  2 minutes to read

It's finally here! 🎉

May 7, 2021  |  1 minute to read

Capturing Alexa Errors with Sentry and GitLab

November 18, 2020  |  4 minutes to read

PDF Gotchas with Headless Chrome

April 15, 2019  |  6 minutes to read