Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: July 6, 2024
The ubiquitous Git versioning system is a way to organize the process of development, writing, and general data change into manageable chunks. One of the main units of a Git repository is the commit. It provides a snapshot of the repository state at a given time. Further, a branch, contrary to its name, represents a single commit by giving it a name. This is similar to the function of a Git tag but extends that with more functionality.
In this tutorial, we explore the limitations of Git branch and tag naming. First, we explore Git names in general. After that, we turn to the restrictions that Git imposes on reference (ref) names, such as those for branches and tags. Finally, we check additional considerations during ref naming.
We tested the code in this tutorial on Debian 12 (Bookworm) with GNU Bash 5.2.15 and Git 2.39.2. Unless otherwise specified, it should work in most POSIX-compliant environments.
Each commit has a commit identifier. However, some commits are more important than others:
That’s why these types of commits can get special names in the form of Git tags, branch names, or other refs (references).
Let’s check all references of an example repository via the show-ref subcommand:
$ git show-ref
6d0264be17baa5e2c0525e5f72e15098156f140d refs/heads/branch1
3b34787f960ce7f140a4a55fb649bf1745c397ff refs/heads/branch2
467173b6e09077c07daad32315f9fa1b661bd675 refs/heads/branch3
ade5f229cc37c52689a4e43c42025c9fd62fca76 refs/heads/master
ae0d1f5879bcfcb771ce1435956934c7e38aec5a refs/tags/base
In this case, we see the main master branch reference (ref) and three other branches. In addition, there’s one tag called base.
However, Git restricts what these names can contain based on what they refer to.
The rules according to which we can name branches and tags are part of the Git documentation.
Just like UNIX paths, a / forward slash is the way to separate components within a ref:
ref/heads/branch1
However, there are several restrictions to the use of slashes:
This way, we can build a hierarchy, since refs also exist as part of the filesystem:
$ tree .git/refs/
.git/refs/
├── heads
│ ├── branch1
│ ├── branch2
│ ├── branch3
│ └── master
└── tags
└── base
3 directories, 5 files
Here, we can see the subdirectories and structure under the refs directory.
Still, the components on either side of a slash can’t begin with a . dot or end with .lock.
Effectively, this avoids two potential sources of confusion:
While these restraints are anchored, some character combinations can’t occur anywhere in the ref name.
Mainly to avoid problems with parsing as well as confusion between a ref and special shell functionality, there are a number of sequences that are considered invalid anywhere in a ref:
In short, the above restrictions avoid problems in notations like branch1..branch2, ^branch1, and parent operations like ~ and ^. Similarly, : colons are sometimes separators between source and destination refs, while @{ is a way to access reflog entry.
Although the ref itself can contain the @ at sign, refs cannot be named with just the @ character in many git versions. \
Naturally, special refs like HEAD aren’t valid custom ref names.
Although not officially documented as problematic, some names and characters cause issues in Git refs due to the nature of the calling context.
In particular, including shell characters that require escaping within double quotes can lead to unexpected results.
For instance, we might want to include an angle bracket in a tag name:
$ git tag more>changes 601fea3
Of course, without single quotes around more>changes, we tag 601fea3 but with more. The rest of the tag name creates the changes file via redirection.
Similarly, using dollar signs can interpolate strings as variable values:
$ git tag dollar$bills 601fea3
In this case, if the $bills variable doesn’t exist, we just tag the commit with dollar. Otherwise, the tag might be completely different.
Finally, path length restrictions apply to refs as well.
In this article, we explored naming in Git.
In conclusion, although the reference names are structured just like a typical UNIX filesystem, there are some additional restrictions that apply to them.