2016-04-26 55 views
2

如何在指定的提交中獲取文件的SHA哈希值?我可以使用git log file來獲取所有提交的文件,但是如何在每個特定提交中獲得文件的SHA哈希值?在特定提交中獲取文件的SHA哈希

我想我可以通過檢查提交併使用git-hash-object來實現,但必須有更簡單的方法。

+0

你需要的僅僅是文件內容逐字SHA1,或者你想用來存儲在Git的歷史文件中的Blob對象的SHA1? – knittl

+0

我是否正確理解blob對象包含文件模式和內容?如果這是區別,我只需要文件內容,就像運行'sha1sum file'一樣。 – Paladin

+0

blob包含其他類型和長度信息以及一些空字節 – knittl

回答

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 <[email protected]> 
Date: Sun Apr 3 10:11:35 2016 -0700 

    Git 2.8.1 

    Signed-off-by: Junio C Hamano <[email protected]> 

: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

驗證並擴展到所有40位數字顯示哈希爲RelNotes,這是符號鏈接指向Documentation/RelNotes對應於一個給定的版本下,一路上版本2.8.1的歷史:

$ git log --raw v2.8.1 -- RelNotes 
commit d95553a6b8c5153f541adcfc3346004e8249b0e6 
Author: Junio C Hamano <[email protected]> 
Date: Sun Apr 3 10:11:35 2016 -0700 

    Git 2.8.1 

    Signed-off-by: Junio C Hamano <[email protected]> 

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

commit c9906e47c065940bfe1a9992da494a8f437a49ac 
Author: Junio C Hamano <[email protected]> 
Date: Tue Jan 12 15:20:51 2016 -0800 

    First batch for post 2.7 cycle 

    Signed-off-by: Junio C Hamano <[email protected]> 

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

commit 24a00ef646974be49ef7138239c3803805400797 
Author: Junio C Hamano <[email protected]> 
Date: Mon Oct 5 12:58:10 2015 -0700 

    Start cycle toward 2.7 

    Signed-off-by: Junio C Hamano <[email protected]> 

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

使用--abbrev選項獲取的所有40個十六進制數字哈希值。這裏的輸出會顯得非常瑣碎,因爲git show的輸出涵蓋了v2.8.1標記和提交到v2.8.1點。

$ git show --raw --abbrev=40 v2.8.1 
tag v2.8.1 
Tagger: Junio C Hamano <[email protected]> 
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 <[email protected]> 
Date: Sun Apr 3 10:11:35 2016 -0700 

    Git 2.8.1 

    Signed-off-by: Junio C Hamano <[email protected]> 

: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

斑點的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行,我們告訴混帳,我們只想要SHA-1提交的哈希值爲RelNotes(限於最近三次與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

至少,你不需要檢查提交。 git show可以直接顯示一個對象,包括一個blob。你可以將它發送到git散列對象,而不用檢查它。

我覺得應該有一個更有效的方式,但你可以做

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

因此,例如,

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

提交的樹已經有一個指向blob對象(文件)的指針。根據OP的要求,這可能就足夠了。 – knittl

+0

太棒了,非常感謝。而且它的速度相當快,在整個項目歷史更改文件的3秒以內。這將幫助我很多腳本:)再次感謝 – Paladin

+0

@ zebediah49:雖然有一個問題,它爲什麼顯示不同於'sha1sum file'的字符串?我的工作樹沒有任何改變,所以我期望第一個散列與'sha1sum file'的輸出相同......我使用這個:'在$(git log --oneline path/to/file | cut -d \ -f1);做git散列對象<(git show $ commit:path/to/file);完成' – Paladin

2

有一個非常快速的方式來獲取Git的哈希值的內的一些文件提交:

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

Git的哈希是SHA-1後面加一個空格字blob的,其次是一個十進制ASCII字符串賦予以字節爲單位的文件,接着是NUL字節大小,其次是該文件的內容:

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

像你想的實際SHA-1它看起來與意見,不過,該文件的內容(如別人會通過提取該文件,並運行它sha1sum得到),而不是混帳哈希:

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

是普通(非bash的特異性)方法(bash的<(是很好,只要確保你已安裝fdesc文件系統)。