0

我一直在使用 'git rev-parse HEAD:' 来计算工作树中文件夹的哈希值。这与 'git ls-tree :' 的行为基本相同。

这不是计算当前工作树的哈希,而是计算特定提交(在我的情况下为 HEAD)的哈希,因此对工作树的更改(修改、新文件、删除、暂存)不是计算的一部分。

现在我想更改我的逻辑以包含这些更改,以计算文件夹的哈希值,但从工作树当前状态而不是提交计算。最好使用与 ls-tree 相同的逻辑(因为到目前为止我们已经使用了此代码,并且希望保持兼容性)。

如何才能做到这一点?非常感谢任何帮助

4

1 回答 1

0

您从一个误解开始:Git 不存储文件夹,因此不散列文件夹。你可能仍然可以做你想做的事。

Git 存储:

  • 文件内容(作为“blob 对象”):blob 对象的哈希 ID 是 word 的校验和blob、空格、文件的十进制大小(以字节为单位)、NUL 字节和文件字节(按所有内容的顺序)被视为单个 8 位字节,即在 Python 中您将f"blob {len(data)}\0".encode() + data用作哈希器的输入);

  • 树对象(存储名称、模式和哈希元组):这些是文件名和 blob 哈希最终存储在提交中的方式,尽管这里有一些复杂性:排序顺序特别重要,名称被分解为组件;

  • 提交对象;和

  • 带注释的标签对象。

与 blob 对象一样,树、提交和带注释的标记对象在前面都有标题,由类型、空格、大小(十进制 ASCII 数字表示)和 NUL 字节组成。这三个的类型字符串分别是treecommittag

正如您所注意到的,结果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>是唯一的可能会很好。

于 2022-02-21T08:51:45.040 回答