为何`git update-ref -d`命令不删除空的父目录?
git update-ref -d a bug? Short answer: No, this is not a bug — it's intentional behavior in Git's plumbing commands like git update-ref.
Let's break down why this happens:
- When you create a nested reference like
refs/foo/bar/baz,git update-refautomatically creates all necessary parent directories (foo/bar) as a convenience, so you don't have to manually set up each directory level to store thebazref file. - When you delete the ref with
git update-ref -d refs/foo/bar/baz, Git only removes the immediate empty parent directory (bar), not the grandparent (foo). The core reasoning here is conservatism: Git has no way of knowing if you plan to use thefoodirectory for other references later (likerefs/foo/quxorrefs/foo/another/ref). Recursively deletingfoocould accidentally wipe out a directory you intended to keep for future custom refs.
Your example clearly illustrates this 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
If you do want to clean up the empty foo directory, you'll need to handle it manually with a command like:
rmdir .git/refs/foo
Just double-check that the directory is truly empty first — Git won't block you from removing it if there are hidden refs or files inside.
This design fits Git's plumbing command philosophy: they do exactly what you explicitly ask, without making assumptions about your future intentions. Porcelain commands (like git branch or git tag) handle more opinionated cleanup for standard refs, but since custom non-standard refs are user-defined, Git leaves upper-level directory management to you.
内容的提问来源于stack exchange,提问作者kini

