如何计算目录的git hash-object?

时间:2011-05-15 20:53:28

标签: git

有没有人有一个在目录上使用git hash-object的例子?它在文件*上很容易工作,但不能像我期望的那样工作**

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

当我尝试在目录中使用hash-object时,它会抱怨“致命:无法打开'C:\ someDirectory':权限被拒绝”

7 个答案:

答案 0 :(得分:14)

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

git mktree了解您所获得格式的输入(例如)git ls-tree HEAD。有一个使用Git Community Book中的git hash-objectgit mktree从头开始构建树的好例子。

答案 1 :(得分:4)

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

git ls-files -s somedirectory | git hash-object --stdin

这给出了一个考虑文件名和内容的哈希。

它的工作原理如下。 git ls-files -s ....将文件列表及其哈希值作为文本输出到stdout,然后git hash-object为从stdin收到的数据生成哈希值。

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

默认情况下,git ls-files也会列出子目录中的文件。如果您不想要,请尝试查看answers to "how to git ls-file for just one directory level。还有其他各种options to git ls-files,包括指定要包含的文件列表的功能。

(*)排除哈希冲突

答案 2 :(得分:2)

我遇到了同样的问题并且攻击了Python script to hash a complete directory。它在某种意义上是有限的,因为它没有考虑.gitignore文件,但到目前为止它已经达到了它的目的(哈希目录,make commit object,store it on the gh-pages branch)。

答案 3 :(得分:1)

我希望通过提供他的脚本的修改版本来改进@Fred Foo答案,其不同之处在于它不会将文件和目录存储在存储库中作为计算其哈希值的副作用: http://pastebin.com/BSNGqsqC

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

此脚本也基于What is the internal format of a git tree object?

的答案

一般的想法是使用git hash-object -- data.txt来获取文件的哈希值,并使用git hash-object --stdin -t tree < TreeDescription来获取目录,其中:

  • TreeDescription是"mode name\0hash"
  • 的串联
  • mode对于文件是"100644",对于目录是"40000"(注意目录中缺少前导零)
  • modename由一个空格隔开,
  • namehash由单个字节\0
  • 分隔
  • hash是一个20字节长的对象散列的二进制表示
  • 条目按name排序,这似乎不是创建树对象所必需的,但通过比较它们的哈希值有助于确定两个目录是否相同 - 遗憾的是我不知道这里应该使用哪种排序算法(特别是:非ascii字符时该怎么做)

另请注意,此二进制格式与树对象存储在存储库中的方式略有不同,因为它缺少"tree SIZE\0"标题。

显然你必须从最深的文件开始自下而上计算,因为在计算父级的哈希值之前你需要所有孩子的哈希值。

答案 4 :(得分:1)

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

import androidx.test.platform.app.InstrumentationRegistry

Kotlin ex
   InstrumentationRegistry.getInstrumentation().context,

无需使用其他需要额外处理的命令。

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

git rev-parse HEAD:some/directory

答案 5 :(得分:0)

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

<强> $ ./a.out 9999999 5000001

来源: http://git-scm.com/docs/git-write-tree

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

<强> git write-tree

我的遗失树对象已经创建了。从这里你可以继续使用:

<强> git write-tree path/to/missing/folder

如下所述: https://git.wiki.kernel.org/index.php/GitFaq#How_to_fix_a_broken_repository.3F

答案 6 :(得分:-1)

Mark Longair说,mktree是可行的方式。

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

git ls-files -s directory_path

这将为您提供包含哈希值的目录内容列表。

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

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