git - 为什么`git update-ref -d`不删除空的父目录?
问题描述
git 中有多种类型的 ref,其中最常见的一些是分支(存储在 中.git/refs/heads
)、远程跟踪分支(.git/refs/remotes
)和标签(.git/refs/tags
)。
但是也可以创建和使用任意的非标准 refs,这些 refs 存在于.git/refs
. 这对于将自定义元数据存储在您不希望用户直接与之交互的存储库中很有用。例如,GitHub 使用这些类型的 refs 来公开对 pull request 分支的引用,并且 Emacs git 客户端Magit在启用适当的设置时使用它们定期保存未提交的更改。此类引用通常需要使用 git 的所谓“管道”命令进行操作,因为面向用户的“瓷器”命令不了解或不支持它们。
我正在使用管道命令玩非标准参考,git update-ref
并发现了一些奇怪的行为:
$ 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
当我创建 refrefs/foo/bar/baz
时,git update-ref
创建了必要的父目录。当我删除 ref 时,它很聪明地删除了 parent directory bar
,该目录现在已变为空。但是,删除“祖父母”目录还不够聪明,删除后该目录foo
现在也是空bar
的。
这是一个错误吗?
解决方案
不,这是设计使然。这是源代码中的注释:
/*
* Remove empty parent directories associated with the specified
* reference and/or its reflog, but spare [logs/]refs/ and immediate
* subdirs. flags is a combination of REMOVE_EMPTY_PARENTS_REF and/or
* REMOVE_EMPTY_PARENTS_REFLOG.
*/
static void try_remove_empty_parents(struct files_ref_store *refs,
const char *refname,
unsigned int flags)
{
如果我将我的非标准 ref 嵌套更深一层,例如refs/foo/bar/baz/xyzzy
,我会注意到父目录和祖父目录都被删除了,但曾祖父目录没有,这使得这种行为更加明显是故意的.
.git/refs/
我想这个想法是(如在我的示例中)下的顶级子目录foo
代表一种类型的 ref 而不是作为 ref 名称的一部分,因此将它们与树下方的目录区别对待(如bar
在我的示例中)使得感觉。
推荐阅读
- java - 在 Selenium 中使用 Gmail API 无法正常获取电子邮件主题
- python - 在 macOS [python, PySimpleGUI, Tkinter, macOS] 中通过 tkinter 非常慢的窗口刷新(更新)
- apache - Apache 反向代理背后的 Radarr 问题
- azure - Azure Lighthouse 入职客户不在客户列表中
- ruby-on-rails - Rails 延迟的工作给出了禁止的错误?
- simulation - 如何计算边界上的拉普拉斯模板?
- image - 如何在从 QuPath 同时导出多个注释时添加注释标签?
- sybase - 如何在数据夹中使用打印
- android - android上markdown中的弹出消息
- android - 处理程序用 shadowOf(getMainLooper()).idle() 消息打破了我的 Robolectric 测试