There are various types of refs in git, some of the most common of which are branches (stored in .git/refs/heads
), remote-tracking branches (.git/refs/remotes
), and tags (.git/refs/tags
).
But it's also possible to create and use arbitrary non-standard refs that live elsewhere under .git/refs
. This can be useful for storing custom metadata in the repository that you don't expect users will want to interact with directly. For example, GitHub uses these kinds of refs to expose references to pull request branches, and the Emacs git client Magit uses them to save uncommitted changes periodically, when the appropriate setting is enabled. Such refs would generally need to be manipulated using the so-called "plumbing" commands of git, since the user-facing "porcelain" commands don't know about or support them.
I was playing around with non-standard refs using the plumbing command git update-ref
and found some odd behavior:
$ git init foo && cd foo
$ touch a && git add a && git commit -m init
$ tree .git/refs
.git/refs
├── heads
│ └── master
└── tags
2 directories, 1 file
$ git update-ref refs/foo/bar/baz HEAD
$ tree .git/refs
.git/refs
├── foo
│ └── bar
│ └── baz
├── heads
│ └── master
└── tags
4 directories, 2 files
$ git update-ref -d refs/foo/bar/baz
$ tree .git/refs
.git/refs
├── foo
├── heads
│ └── master
└── tags
3 directories, 1 file
When I created the ref refs/foo/bar/baz
, git update-ref
created the necessary parent directories. When I deleted the ref, it was smart enough to remove the parent directory bar
, which had now become empty. However, it wasn't smart enough to remove the "grandparent" directory foo
, which was also now empty after removing bar
.
Is this a bug?