git的半秘密空树对象是否可靠,为什么没有符号名称呢?

tor*_*rek 107 git

Git有一个众所周知的,或者至少是众所周知的空树,其SHA1是:

4b825dc642cb6eb9a060e54bf8d69288fbee4904
Run Code Online (Sandbox Code Playgroud)

(你可以在任何仓库中看到这个,甚至是新创建的仓库,用git cat-file -tgit cat-file -p).

如果您努力工作并且非常小心,您可以使用这个空树来存储没有文件的目录(请参阅如何将空目录添加到git存储库的答案),尽管这不是一个好主意.

它作为一个参数更有用git diff-tree,其中一个示例钩子可以做到.

我想知道的是,

  1. 这有多可靠 - 即,某些未来版本的git没有编号的git对象4b825dc642cb6eb9a060e54bf8d69288fbee4904
  2. 为什么空树没有符号名称(或者有一个?).

(创建符号名称的快速而肮脏的方法是将SHA1放入,例如,.git/Nulltree不幸的是,您必须为每个repo执行此操作.似乎更好地将幻数放在脚本中等等.我只是有一般的厌恶到魔术数字.)

Von*_*onC 94

这个帖子提到:

如果您不记得空树sha1,您始终可以使用以下方法派生它:

git hash-object -t tree /dev/null
Run Code Online (Sandbox Code Playgroud)

或者,正如Ciro Santilli 在评论中提出的那样:

printf '' | git hash-object --stdin -t tree
Run Code Online (Sandbox Code Playgroud)

或者,如此处所见,来自Colin Schimmelfing:

git hash-object -t tree --stdin < /dev/null
Run Code Online (Sandbox Code Playgroud)

因此,我认为将该命令的结果定义为空的sha1树(而不是依赖于"众所周知的值")更安全.


注意,当作者想要第一次提交为空时,你会看到SHA1弹出一些GitHub 仓库(参见博客文章" 我如何初始化我的Git存储库 "):

$ 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'
Run Code Online (Sandbox Code Playgroud)

会给你:

空树SHA1

(参见树SHA1?)

您甚至可以在该空提交之上重新定义现有历史记录(请参阅" git:如何插入提交作为第一个,转移所有其他提交? ")

在这两种情况下,您都不依赖于该空树的确切SHA1值.
您只需遵循最佳实践,使用第一个空提交初始化您的仓库.


要做到这一点:

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"
Run Code Online (Sandbox Code Playgroud)

这将生成一个特定于您的repo,用户名,电子邮件,创建日期的SHA1的提交(意味着提交本身的SHA1每次都不同).
但该提交引用的树将是4b825dc642cb6eb9a060e54bf8d69288fbee4904空树SHA1.

git log --pretty=raw

commit 9ed4ff9ac204f20f826ddacc3f85ef7186d6cc14
tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904      <====
author VonC <vonc@laposte.net> 1381232247 +0200
committer VonC <vonc@laposte.net> 1381232247 +0200

    initial empty commit
Run Code Online (Sandbox Code Playgroud)

仅显示提交树(显示提交树SHA1):

git show --pretty=format:%T 9ed4ff9ac204f20f826ddacc3f85ef7186d6cc14
4b825dc642cb6eb9a060e54bf8d69288fbee4904
Run Code Online (Sandbox Code Playgroud)

如果提交引用空树,确实是您的第一次提交,则可以显示空树SHA1:

git log --pretty=format:%h --reverse | head -1 | xargs git show --pretty=format:%T
4b825dc642cb6eb9a060e54bf8d69288fbee4904
Run Code Online (Sandbox Code Playgroud)

(甚至适用于Windows,使用Gnu On Windows命令)


正如下面的评论,使用git diff <commit> HEAD,这将显示在目前的分公司负责所有的文件:

git diff --name-only 4b825dc642cb6eb9a060e54bf8d69288fbee4904 HEAD
Run Code Online (Sandbox Code Playgroud)

注意:正式定义了空树值cache.h.

#define EMPTY_TREE_SHA1_HEX \
    "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
Run Code Online (Sandbox Code Playgroud)

它现在(Git 2.16,2018年第一季度),在一个不再绑定到(仅)SHA1的结构中使用,如commit eb0ccfd中所示:

切换空树和blob查找以使用哈希抽象

切换使用empty_tree_oidempty_blob_oid使用current_hash表示当前正在使用的哈希算法的抽象.

查看更多" 为什么Git不使用更现代的SHA? "


Oll*_*leg 5

这是有关如何创建空树提交的答案,即使在存储库尚未为空的情况下也是如此。 /sf/answers/1023642091/

但我更喜欢“空”作为标签,而不是分支。简单的方法是:

git tag empty $(git hash-object -t tree /dev/null)
Run Code Online (Sandbox Code Playgroud)

因为标签可以直接指向树状结构,无需提交。现在获取工作树中的所有文件:

git diff --name-only empty
Run Code Online (Sandbox Code Playgroud)

或者与 stat 相同:

git diff --stat empty
Run Code Online (Sandbox Code Playgroud)

所有文件作为差异:

git diff empty
Run Code Online (Sandbox Code Playgroud)

检查所有文件中的空格:

git diff --check empty
Run Code Online (Sandbox Code Playgroud)