Is git's semi-secret empty tree object reliable, and why is there not a symbolic name for it?
Git有一个众所周知的,或者至少是众所周知的空树,其SHA1是:
1 | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 |
(您可以在任何仓库中看到这一点,即使是新创建的仓库,也可以使用
如果您努力工作并且非常小心,您可以使用这个空树来存储没有文件的目录(请参阅如何将空目录添加到git存储库的答案),尽管这不是一个好主意。
它作为
我想知道的是,
(创建符号名称的快速而肮脏的方法是将SHA1放入,例如,
这个帖子提到:
If you don't remember the empty tree sha1, you can always derive it with:
1 | git hash-object -t tree /dev/null |
或者,正如Ciro Santilli在评论中提出的那样:
1 | printf '' | git hash-object --stdin -t tree |
或者,如此处所见,来自Colin Schimmelfing:
1 | git hash-object -t tree --stdin < /dev/null |
因此,我认为将该命令的结果定义为空的sha1树(而不是依赖于"众所周知的值")更安全。
注意,当作者想要第一次提交为空时,你会看到SHA1弹出一些GitHub仓库(参见博客文章"我如何初始化我的Git存储库"):
1 | $ GIT_AUTHOR_DATE="Thu, 01 Jan 1970 00:00:00 +0000" GIT_COMMITTER_DATE="Thu, 01 Jan 1970 00:00:00 +0000" git commit --allow-empty -m 'Initial commit' |
会给你:
(参见树SHA1?)
您甚至可以在该空提交之上重新定义现有历史记录(请参阅"git:如何插入提交作为第一个,转移所有其他提交?")
在这两种情况下,您都不依赖于该空树的确切SHA1值。
您只需遵循最佳实践,使用第一个空提交初始化您的仓库。
要做到这一点:
1 2 3 4 5 6 | git init my_new_repo cd my_new_repo git config user.name username git config user.email email@com git commit --allow-empty -m"initial empty commit" |
这将生成一个特定于您的repo,用户名,电子邮件,创建日期的SHA1的提交(意味着提交本身的SHA1每次都不同)。
但该提交引用的树将是
1 2 3 4 5 6 7 8 | git log --pretty=raw commit 9ed4ff9ac204f20f826ddacc3f85ef7186d6cc14 tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 <==== author VonC <[email protected]> 1381232247 +0200 committer VonC <[email protected]> 1381232247 +0200 initial empty commit |
仅显示提交树(显示提交树SHA1):
1 2 | git show --pretty=format:%T 9ed4ff9ac204f20f826ddacc3f85ef7186d6cc14 4b825dc642cb6eb9a060e54bf8d69288fbee4904 |
如果提交引用空树,确实是您的第一次提交,则可以显示空树SHA1:
1 2 | git log --pretty=format:%h --reverse | head -1 | xargs git show --pretty=format:%T 4b825dc642cb6eb9a060e54bf8d69288fbee4904 |
(甚至适用于Windows,使用Gnu On Windows命令)
如下所示,使用
1 | git diff --name-only 4b825dc642cb6eb9a060e54bf8d69288fbee4904 HEAD |
注意:空树值在
1 2 | #define EMPTY_TREE_SHA1_HEX \ "4b825dc642cb6eb9a060e54bf8d69288fbee4904" |
它现在(Git 2.16,2018年第一季度),在一个不再绑定到(仅)SHA1的结构中使用,如commit eb0ccfd中所示:
Switch empty tree and blob lookups to use hash abstraction
Switch the uses of
empty_tree_oid andempty_blob_oid to use thecurrent_hash abstraction that represents the current hash algorithm in
use.
查看更多"为什么Git不使用更现代的SHA?"
以下是即使在存储库尚未为空的情况下如何创建空树提交的答案。
https://stackoverflow.com/a/14623458/9361507
但我更喜欢"空"来标记,而不是分支。简单的方法是:
1 | git tag empty $(git hash-object -t tree /dev/null) |
因为tag可以直接指向tree-ish而不提交。
现在获取工作树中的所有文件:
1 | git diff --name-only empty |
或者与stat相同:
1 | git diff --stat empty |
所有文件为diff:
1 | git diff empty |
检查所有文件中的空格:
1 | git diff --check empty |
我写了一篇博文,其中有两种不同的方法可以找到哈希:http://colinschimmelfing.com/blog/gits-empty-tree/
如果由于某种原因它永远改变,你可以使用以下两种方式来找到它。但是,我会非常自信地使用.bashrc别名中的哈希等,我认为它不会很快改变。至少它可能是git的主要版本。
这两种方式是: