Git - 如何通过 SHA1 值找到文件名

48

我使用以下命令将文件添加到索引:

git add somefile.txt

我随后使用以下命令获取了该文件的SHA1:

git hash-object somefile.txt

我现在有一个SHA1值,我想使用这个SHA1值从索引中检索对象的文件名。

git show 5a5bf28dcd7944991944cc5076c7525439830122

这个命令返回文件内容,但不包含文件名。

如何从SHA1中获取完整的文件名和路径?


相关问题 - Albert
6个回答

38

在git中,没有直接的映射关系可以从SHA1哈希值中获取文件名,因为文件名是包含该文件的树对象的一部分,而不是文件内容的blob对象。

想要从SHA1哈希值中检索文件名并不是一个常见的操作,也许你可以提供一个实际使用案例来详细说明一下?

如果你正在查看当前文件(即HEAD提交),你可以尝试以下方法。

git ls-tree -r HEAD | grep <SHA1>

如果你想查找以前提交的内容,你需要做类似于这样的事情。

git rev-list <commit-list> | \
xargs -n1 -iX sh -c "git ls-tree -r X | grep <SHA1> && echo X"

7
如果你不知道在<commit-list>中输入什么, --all会在代码库的所有分支中进行搜索。 - EoghanM
1
我的版本的 git ls-tree 只接受一个修订版本作为参数 (git v1.7.4.4)。我将你的版本改编成了 for rev in $(git rev-list --all); do git ls-tree -r $rev | grep $SHA; done | uniq - Daniel Böhmer
@halo:我相当确定每个人的 ls-tree 都只需要一个修订参数,这就是为什么我在 xargs 中使用 -n1 的原因。 - CB Bailey
@CharlesBailey:啊,从未听说过“-n”选项。看起来非常有用。感谢您的提示!但是,上面列出的命令对我没有起作用。不知道为什么,但幸运的是在此期间解决了我的问题。 - Daniel Böhmer
太好了,正是我需要的。如果你想要一个真实的使用案例,我刚刚推送了一个分支,但是git提示有一个文件太大了,但我只上传了几个小文件,并不知道SHA1与哪个文件相关。使用你的答案,我能够找出哪个文件太大了! - sij_a
显示剩余3条评论

36

有一个很棒的一行代码可以实现这个:

git rev-list --objects --all | grep <blob sha1>

3
对于两种情况,它都能够正常工作:(1)所有的 blob 都是唯一的;或者(2)你只对具有匹配哈希的最新的 blob 感兴趣。例如,在我的代码库中,它会忽略掉具有相同哈希值的第二个旧的 blob。虽然如此,它仍然非常有用。已经在 git v2.20 中进行了测试。 - akhan
1
这很棒。你还会继续使用这个方法,还是现在用 git describe <sha1> 更好? - Harold

9
下面的shell脚本很大程度上基于哪个提交包含这个Blob?和Aristotle Pagaltzis提供的答案。
#!/bin/sh

obj_hash=$1

# go over all trees
git log --pretty=format:'%T %h %s' \
| while read tree commit subject ; do
     git ls-tree -r $tree | grep  "$obj_hash" \
     | while read a b hash filename ; do
        if [ "$hash" == "$obj_hash" ]; then
          f=$filename
          echo $f
          break
        fi
        if $f ; then break; fi
      done
      if $f; then break; fi
done

我相信有人可以美化这个脚本,但它确实有效。思路是查看所有提交的树,并搜索您特定的哈希值。

4

git rev-list <commit-list>不会包括任何被rebase -i移除并且现在仅由reflog引用的提交,因此如果上述命令未找到blob,则应该检查reflog,例如:

git reflog --all | \
cut -d\  -f1 | \
xargs -n1 -iX sh -c "git ls-tree -r X | grep <BLOB_SHA> && echo X"

1

在另一个答案中,@Harold的评论得到了拓展。这个命令将会给你文件被引入的提交和该提交上文件的路径:

git describe --always <blob-hash>

测试于 git 版本 2.30.2。


-1

提交文件并记录提交对象的sha1哈希值。之后使用

git ls-tree <commit-sha1>

然后您将获得带有哈希值的文件名称。

查看手册页面以获取更多选项。


2
这是提交的SHA,OP询问文件的SHA。 - Amedee Van Gasse

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