在特定提交中获取文件的SHA哈希

时间:2016-04-26 18:30:17

标签: git

如何在指定的提交中获取文件的SHA哈希?我可以使用git log file获取所有触及文件的提交,但是如何在每个特定提交中获取文件的SHA哈希?

我认为我可以通过检查提交而不是使用git-hash-object来实现,但必须有更简单的方法。

3 个答案:

答案 0 :(得分:3)

git showgit log是近亲和共享选项。您的问题询问了与特定提交相关联的文件的SHA-1对象名称,但同时也提供了历史记录中每次提交的相同信息。

--raw选项提供您所追求的信息。以下示例将使用git自己的存储库。

要显示使用特定提交更改的文件,请使用git showgit log -1。后者不会为标记对象生成输出,而只生成标记的提交。

$ git log -1 --raw v2.8.1
commit d95553a6b8c5153f541adcfc3346004e8249b0e6
Author: Junio C Hamano <gitster@pobox.com>
Date:   Sun Apr 3 10:11:35 2016 -0700

    Git 2.8.1

    Signed-off-by: Junio C Hamano <gitster@pobox.com>

:000000 100644 0000000... ef6d80b... A  Documentation/RelNotes/2.8.1.txt
:100644 100644 adc940b... 8afe349... M  Documentation/git.txt
:100755 100755 4e9450b... 46595da... M  GIT-VERSION-GEN
:120000 120000 7db3040... d40c3e1... M  RelNotes

每个更改行包含

  • 开始或源模式(000000表示已创建或未合并)
  • 结果或目标模式(000000表示已删除或未合并)
  • 源SHA-1(全部为零创建)
  • 目标SHA-1(全部删除零)
  • 状态代码加上可选的数字分数(A以上是加法和M修改)
  • 路径

有关详细信息,请参阅“Raw output format” in git diff’s documentation

与v2.8.1标记关联的文件RelNotes的SHA-1对象名称是d40c3e1,我们可以使用

验证并扩展到所有四十位数字
$ git rev-parse v2.8.1:RelNotes
d40c3e126c03b0e4bd9c6162f63a35a45f5e9020

要显示RelNotes的哈希值,这是一个指向对应于给定版本的Documentation/RelNotes下的符号链接,沿着版本2.8.1的历史记录显示:

$ git log --raw v2.8.1 -- RelNotes
commit d95553a6b8c5153f541adcfc3346004e8249b0e6
Author: Junio C Hamano <gitster@pobox.com>
Date:   Sun Apr 3 10:11:35 2016 -0700

    Git 2.8.1

    Signed-off-by: Junio C Hamano <gitster@pobox.com>

:120000 120000 7db3040... d40c3e1... M  RelNotes

commit c9906e47c065940bfe1a9992da494a8f437a49ac
Author: Junio C Hamano <gitster@pobox.com>
Date:   Tue Jan 12 15:20:51 2016 -0800

    First batch for post 2.7 cycle

    Signed-off-by: Junio C Hamano <gitster@pobox.com>

:120000 120000 3ba13ce... 7db3040... M  RelNotes

commit 24a00ef646974be49ef7138239c3803805400797
Author: Junio C Hamano <gitster@pobox.com>
Date:   Mon Oct 5 12:58:10 2015 -0700

    Start cycle toward 2.7

    Signed-off-by: Junio C Hamano <gitster@pobox.com>

:120000 120000 def6ebd... 3ba13ce... M  RelNotes
[...]

使用--abbrev选项获取散列的所有四十位十六进制数字。这里的输出看起来更加繁琐,因为git show的输出涵盖了v2.8.1标记和v2.8.1指向的提交。

$ git show --raw --abbrev=40 v2.8.1
tag v2.8.1
Tagger: Junio C Hamano <gitster@pobox.com>
Date:   Sun Apr 3 10:14:32 2016 -0700

Git 2.8.1
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAABAgAGBQJXAU94AAoJELC16IaWr+bLopQQAONTo52BGPCr7exw757SKY90
gYsHDxTaNpPtGZS7ltdOiEESPG3Mx3w1OYk7CBPtxjBLM+JvEdcZsCKrs/RlTrKL
lTc53WHC1tUa8EYjEyHNq4z0E2y4tCTNsj5eD2n/lAdTn2SK59bL4DEouDP2mYJU
3pUkujD9tu/ATw1s77VNiHxcrg9V9TdltaP2+lkHPzXXx8fb8kkabFRkzqvQdgfe
Qe0mZEHKRZY4nEO16dKukalxyWW0iMfoSVeRTjJiQU4HEcMyEnG3lfKeI1ddKVTQ
+XfAM6QianXqdfHRt5ol9MwCm9HAcGWu82caIBOTsc3L7bDrbJTTkDOvwpmVUDJi
WcqgocDGr/x7RA0/E8bqoIv40UXx07DzBTv3mKBo2CMvkow6pgQjsKKfPrvoNKyC
qFqp07A3UXgLWeWLF2iaYJklkq2jEeLPKOCJ1lJcPUg+Kk20+FQEo1XPERnrosoz
xHDDMBy7Vnvd0ij8Ipaxj2XHfIVYHC/WcrfsjiRYa1sHMjdTw/6I0tdtdUkDiY2W
70AsYQUWPtU52tSuK7divMoym3g583bNtu5X+6STDtLZc5XbVAtMEg5PYadTuwci
tTmXTUrti2qLsDp2XZI7rKbKVo5JyW8BYC8BeLUwgVnkj9svG5+6rlTKtgXa+hCo
L9gDU1Iie03IlIHnL+/s
=NLvn
-----END PGP SIGNATURE-----

commit d95553a6b8c5153f541adcfc3346004e8249b0e6
Author: Junio C Hamano <gitster@pobox.com>
Date:   Sun Apr 3 10:11:35 2016 -0700

    Git 2.8.1

    Signed-off-by: Junio C Hamano <gitster@pobox.com>

:000000 100644 0000000000000000000000000000000000000000 ef6d80b008a0a7970238404b034593be27e933c3 A      Documentation/RelNotes/2.8.1.txt
:100644 100644 adc940bf7591069c74c9b47aa5e5686e0438d606 8afe349781d57527083fdb75511959fd25a4239b M      Documentation/git.txt
:100755 100755 4e9450b3ae0c403820f0166435c52c4ea74e7451 46595dad2234f861198347ef8f4f60d167061709 M      GIT-VERSION-GEN
:120000 120000 7db30403c3471e15f4f15a5e68016d7926b3e3de d40c3e126c03b0e4bd9c6162f63a35a45f5e9020 M      RelNotes

blob的SHA-1对象名称(git如何表示文件内容)与在文件上运行sha1sum不同,因为git将元数据添加到前面:文字字符串blob,其次是用空格,后跟十进制内容的长度,用NUL字节终止。要计算文件后续版本内容的SHA-1哈希值,请使用

行中的命令。
$ for commit in $(git log --pretty=%H v2.8.1 -- RelNotes | head -3) ; \
    do git show ${commit}:RelNotes | sha1sum ; \
  done
ce5501f9daadf110a20a4e4eccdfed63ef4b27e3  -
bd4d920214c4a48d8820292e24f020690595858d  -
5d47b511d86abd490fa4f2c2a8d4ef3589e1aecf  -

使用--pretty=%H-- RelNotes,我们告诉git我们只想要触及RelNotes的提交的SHA-1哈希值(仅限于head -3最近的三个提交) 。然后,对于每个提交,我们将跟踪的内容提供给sha1sum

如果您更喜欢xargs,则看起来像

$ git log --pretty=%H v2.8.1 -- RelNotes | head -3 |
    xargs -I {} sh -c 'git show {}:RelNotes | sha1sum'
ce5501f9daadf110a20a4e4eccdfed63ef4b27e3  -
bd4d920214c4a48d8820292e24f020690595858d  -
5d47b511d86abd490fa4f2c2a8d4ef3589e1aecf  -

答案 1 :(得分:2)

在一些提交中有一种非常快速的方法来获取文件的Git哈希:

git rev-parse <commit-ID>:/path/to/file

Git的哈希是单词blob的SHA-1,后跟一个空格,后跟一个十进制ASCII字符串,以字节为单位给出文件的大小,后跟一个NUL字节,后跟文件的内容:

size=$(wc -c $file)
(printf "blob %d\0" $size; cat $file) | sha1sum -

从评论看起来,就像你想要文件内容的实际SHA-1(正如其他人通过解压缩文件并在其上运行sha1sum而得到的那样),而不是 git 哈希:

git show <commit-ID>:path | sha1sum -

是一般的(非特定于bash的)方法(bash的<(也没问题,只需确保安装了fdesc文件系统。)

答案 2 :(得分:1)

至少,您不需要签出提交。 git show可以直接显示一个对象,包括一个blob。你可以将它发送到git hash-object而不用检查它。

我认为应该有一种更有效的方法,但你可以做到

git hash-object <(git show [commit]:[path])

所以,例如,

$ git hash-object <(git show master:Makefile)
3fb4e1cbe0019c691a504e3419ece252db6f60ab