您从一个误解开始:Git 不存储文件夹,因此不散列文件夹。你可能仍然可以做你想做的事。
Git 存储:
文件内容(作为“blob 对象”):blob 对象的哈希 ID 是 word 的校验和blob
、空格、文件的十进制大小(以字节为单位)、NUL 字节和文件字节(按所有内容的顺序)被视为单个 8 位字节,即在 Python 中您将f"blob {len(data)}\0".encode() + data
用作哈希器的输入);
树对象(存储名称、模式和哈希元组):这些是文件名和 blob 哈希最终存储在提交中的方式,尽管这里有一些复杂性:排序顺序特别重要,名称被分解为组件;
提交对象;和
带注释的标签对象。
与 blob 对象一样,树、提交和带注释的标记对象在前面都有标题,由类型、空格、大小(十进制 ASCII 数字表示)和 NUL 字节组成。这三个的类型字符串分别是tree
、commit
和tag
。
正如您所注意到的,结果git rev-parse HEAD:
是存储在HEAD
提交中的树对象的哈希 ID。您可以使用 Git 索引中的任何内容构建树对象git write-tree
,尽管索引必须包含所有所需的文件 blob 和路径名,并且此时不得包含任何合并冲突。
要计算某个树的哈希 ID ,请创建一个空索引,1将该树添加到该空索引,然后使用git write-tree
该索引创建一个树对象。此树对象将存储到存储库中。如果你最终从不将它用于任何事情,这有点浪费,但如果你正常操作系统,Git 的 GC 最终会收集它。由于构建树对象的排序和组件化问题,这是直接在 Git 中完成的唯一方法。
在 shell 脚本中,您可以使用以下内容(请注意,这完全未经测试):
export GIT_INDEX_FILE=/tmp/index.test.$$
rm -f $GIT_INDEX_FILE
trap "rm -f $GIT_INDEX_FILE" 0 1 2 3 15
git add .
git write-tree
此命令序列的标准输出是树的哈希 ID(由 打印git write-tree
)。
如果你想用编程语言来做,请参阅我的 Python 代码,但请注意所有限制。
1 Git 实际上并不容忍空索引,而是将不存在的索引文件视为存在但为空。因此,rm -f
作为“创建”“空索引”的行。将索引文件放入git rev-parse --git-dir
而不是/tmp
,和/或使用mktemp
而不是仅仅假设它index.test.<pid>
是唯一的可能会很好。