如何在Git中获取工作副本的树哈希?

3

使用git,我如何获取git目录当前状态的树哈希值?也就是说,如果我运行git add -A后再运行git commit,该提交的树哈希值是什么(而不是提交哈希值)?


请检查链接 https://dev59.com/5ek5XIcBkEYKwwoY597h 是否对您有所帮助。 - Fraddy
可能是重复的问题:如何计算目录的git hash对象? - mkrieger1
1
另一个问题稍微更加普遍,它询问如何获取任意目录的树哈希值,而不仅仅是存储库当前状态的树哈希值。此外,这里的答案要好得多。 - Shum
2个回答

4

Greg Bacon的方法稍微容易一些:

  • 通过复制当前索引创建临时索引
  • 使用git add -A更新临时索引中的所有内容
  • 使用git commit-tree将临时索引转换为实际树

一个小的shell脚本(未经测试)就足够了:

#! /bin/sh -e
export GIT_INDEX_FILE=$(mktemp)
trap "rm -f $GIT_INDEX_FILE" 0 1 2 3 15
cp $(git rev-parse --git-dir)/index $GIT_INDEX_FILE
git add -A && git write-tree

复制当前索引的原因是,如果我们不从真实索引中预先准备临时索引,那么可能被忽略(通过.gitignore或排除文件)但目前正在跟踪的文件(在常规索引中)将在使用临时索引时被忽略。
另请参阅您自己的问题如何在git中获取索引的树哈希?

我接受了这个答案,因为它是最简单的答案,并且正好符合我的要求。很遗憾没有一行代码可以解决这个问题,但三行也足够接近了。 - Shum

1
你可以尝试使用git hash-objectgit mktree来拼凑它,正如The Git Community BookRaw Git章节所描述的那样,但我建议采用更简单的方法,在一个可丢弃的detached HEAD上完成所有工作。
假设你想从当前分支的末端开始,使用以下命令进入detached HEAD状态
git checkout $(git rev-parse HEAD)

git checkout 的聊天输出部分暗示了以这种方式进行操作的优势。

您处于“分离 HEAD”状态。您可以浏览,进行实验性更改并提交它们,并且您可以通过执行另一个 checkout 而舍弃在此状态下所做的任何提交,而不会影响任何分支。

在这里,我创建了新文件,这将为 git 提供一些操作,并代表您的真实更改。

touch new other stuff blah etc

现在不需要重新实现git,让git做它已经做过的事情。
git add -A .

这个阶段会改变索引,从中 git write-tree 可以轻松地创建一个新的树对象。在你的机器和仓库里的输出就是你所询问的哈希值。
git write-tree
afba5669cbf579a9f27f1fda66cb0958282fae3a

标准输出中显示的哈希值是刚创建的树对象的哈希值,但不需要完全相信我的话。
$ git commit -m 'Throwaway commit'
[detached HEAD 0ae9d12] Throwaway commit
 5 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 blah
 create mode 100644 etc
 create mode 100644 new
 create mode 100644 other
 create mode 100644 stuff

输出提示了新提交的SHA1对象名称(0ae9d12),我们可以通过确认。
$ git rev-parse HEAD
0ae9d12408d1ea7eb02821d66f6de8a2f8423e7f

但是您想知道提交的树形对象的哈希值,可通过以下方式寻址:

$ git rev-parse HEAD^{tree}
afba5669cbf579a9f27f1fda66cb0958282fae3a

请注意,哈希值与git write-tree的输出相同。
现在,如果您想保留提交,请使用git branch在此处创建一个新分支。否则,如果您忽略它,提交和未使用的对象将最终作为Git的普通垃圾回收的一部分被丢弃。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接