秘密空树对象可靠,为什么没有它的象征性名称?

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

4b825dc642cb6eb9a060e54bf8d69288fbee4904

(你可以在任何回购中看到这一点,甚至是新创建的,使用git cat-file -tgit cat-file -p )。

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

作为示例钩子之一的git diff-tree一个参数更有用。

我想知道的是,

  • 这有多可靠 - 也就是说,将来的某个版本的git没有一个编号为4b825dc642cb6eb9a060e54bf8d69288fbee4904的git对象?
  • 为什么没有空树的符号名(或者是否有?)。
  • (创建符号名称的一种快速和肮脏的方法是将SHA1放入,例如.git/Nulltree ,但不幸的是,您必须为每个回购操作执行此操作,似乎最好只将幻数放在脚本中,等等。对魔法数字有一般的反感。)


    这个线程提到:

    如果你不记得空树sha1,你总是可以得到它:

    git hash-object -t tree /dev/null
    

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

    printf '' | git hash-object --stdin -t tree
    

    所以我猜想用这个命令的结果定义一个变量作为你的空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'
    

    会给你:

    空树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"
    

    这将生成一个特定于您的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
    

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

    git show --pretty=format:%T 9ed4ff9ac204f20f826ddacc3f85ef7186d6cc14
    4b825dc642cb6eb9a060e54bf8d69288fbee4904
    

    如果该提交引用空树,确实是您的第一次提交,那么您可以使用以下命令显示空树SHA1:

    git log --pretty=format:%h --reverse | head -1 | xargs git show --pretty=format:%T
    4b825dc642cb6eb9a060e54bf8d69288fbee4904
    

    (甚至可以在Windows上使用Gnu On Windows命令)


    正如下面所述,使用git diff <commit> HEAD ,这将显示当前分支中的所有文件HEAD:

    git diff --name-only 4b825dc642cb6eb9a060e54bf8d69288fbee4904 HEAD
    

    注意:空树的值在cache.h正式定义。

    #define EMPTY_TREE_SHA1_HEX 
        "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
    

    现在是(Git 2.16,Q1 2018),用于不再与(仅)SHA1绑定的结构中使用,如commit eb0ccfd所示:

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

    empty_tree_oidempty_blob_oid的用法切换为使用表示当前正在使用的散列算法的current_hash抽象。

    请参阅“为什么Git不使用更现代的SHA?”


    我用两种不同的方式找到了哈希,写了一篇博文:http://colinschimmelfing.com/blog/gits-empty-tree/

    如果由于某种原因而改变,可以使用下面的两种方法来找到它。 不过, 我觉得在.bashrc别名中使用哈希值会很自信,我认为它不会很快改变。 至少它可能是git的主要版本。

    两种方法是:

  • 上面的答案: git hash-object -t tree --stdin < /dev/null
  • 简单地启动一个空的repo,然后在新的repo中运行git write-tree - 这个hash将由git write-tree输出。
  • 链接地址: http://www.djcxy.com/p/57165.html

    上一篇: secret empty tree object reliable, and why is there not a symbolic name for it?

    下一篇: Why does the wc utility generate multiple lines with "total"?