如何计算目录的git哈希对象?

如何计算目录的git哈希对象?,git,Git,有人举过在目录上使用git哈希对象的例子吗?它在一个文件上很容易工作,但不像我期望的那样在一个目录中工作** *: git hash-object c:\somefile.txt **: git hash-object -t tree c:\somedirectory 当我尝试将哈希对象用于目录时,它会抱怨“致命:无法打开'C:\someDirectory':权限被拒绝”git hash object-t tree希望file参数是描述树中条目的文件,而不是文件系统中的目录。我从评论中了解到

有人举过在目录上使用git哈希对象的例子吗?它在一个文件上很容易工作,但不像我期望的那样在一个目录中工作**

*:  git hash-object c:\somefile.txt
**: git hash-object -t tree c:\somedirectory

当我尝试将哈希对象用于目录时,它会抱怨“致命:无法打开'C:\someDirectory':权限被拒绝”

git hash object-t tree
希望file参数是描述树中条目的文件,而不是文件系统中的目录。我从评论中了解到,此命令需要一个以二进制格式描述树的文件,并且使用
git mktree
创建树对象会更容易


git-mktree
理解您从(例如)
git-ls-tree-HEAD
获得的格式输入。这里有一个很好的例子,可以使用中的
git hash object
git mktree
从头开始构建一棵树。

正如Mark Longair所说,mktree是一条可行之路


我也遇到了同样的问题,为了解决它,我付出了很多努力。这就是我所做的:

git ls-files -s directory_path
这将为您提供目录及其哈希的内容列表

然后,您可以在文本编辑器中将此列表转换为ls树格式,然后

echo -e "{ls-tree format list}" | git mkdir

我也有同样的问题,并砍掉了一个。它的局限性在于它没有将
.gitignore
文件考虑在内,但到目前为止它已经达到了它的目的(hash目录、make commit对象等)。

经过长时间的搜索,我发现了以下命令:

git写树

资料来源:

我用它来恢复丢失的目录:

git写入树路径/到/缺少/文件夹

我丢失的树对象被创建了。在此,您可以继续使用:

git散列对象-w path/to/missing/folder/file.txt

如中所述:

我想改进答案,提供他的脚本的修改版本,不同之处在于它不会将文件和目录存储在存储库中,这是计算散列的副作用:

不幸的是,我不知道有什么方法可以强制
git mktree
不在存储库中创建树对象,因此代码必须生成树的二进制表示形式,并将其传递给
git hash object-t tree

这个脚本也是基于

总体思路是使用
git hash object--data.txt
获取文件的哈希值,并使用
git hash object--stdin-t tree
获取目录,其中:

  • TreeDescription是“模式名称\0hash”的串联
  • 模式
    对于文件是
    的“100644”
    ,对于目录是
    的“40000”
    (请注意,对于目录,前导零不存在)
  • 模式
    名称
    由一个空格分隔
  • name
    hash
    由单个字节分隔
    \0
  • 散列
    是对象散列的20字节长的二进制表示形式
  • 条目按
    名称
    排序,这似乎不是创建树对象所必需的,但有助于通过比较它们的散列来确定两个目录是否相等-不幸的是,我不知道这里应该使用哪种排序算法(特别是:在非ascii字符的情况下该怎么办)
还请注意,这种二进制格式与存储库中存储树对象的方式略有不同,因为它缺少
“tree SIZE\0”
标题


显然,您必须从最深的文件开始自下而上地计算,因为在计算父级的哈希之前,您需要对所有子级进行哈希运算。

根据您希望这样做的原因,以下git命令可能会有用:

git ls-files -s somedirectory | git hash-object --stdin
这将给出一个考虑了文件名和内容的散列

它是这样工作的。
git ls files-s..
将文件列表及其哈希值作为文本输出到
stdout
,然后
git hash对象
为它从
stdin
接收的数据生成哈希值

我的用例如下-我想知道一个分支中目录中的(git托管)文件是否与另一个分支中的文件完全匹配(*)。具体用途是比较“目录散列”,决定是否需要重新生成缓存的派生文件

默认情况下,
git ls files
也会列出子目录中的文件。如果你不想那样,试试看。还有各种其他功能,包括指定要包含的文件列表的功能


(*)排除散列冲突

我不确定是否要获取git存储库外部目录的散列,但对于存储库内部的目录,请尝试仅打印散列:

git rev-parse HEAD:some/directory
不需要使用其他需要额外处理的命令

这也会起作用,但会提供您可能不需要的其他信息(如文件模式和其他数据):


我认为
git-ls-tree-HEAD-somedirectory
就足够了,git已经散列了dir。无需
ls files
整个目录并使用
git hash object
重新对其进行灰化。如果您需要限制散列计算中包含的文件,例如特定的文件扩展名,我想我上面的较长解决方案可能会很方便,或者排除子目录。回答得很好。git书不再包含
mktree
示例,GitHub上的源代码也不足以在旧版本中找到它。
git ls-tree HEAD some/directory