2015-07-22 60 views
4

請考慮以下示例。使用git filter-branch和signed commit提供的意外行爲

mkdir pgp-git-test 
cd pgp-git-test 
git init 
touch a.txt 
git add a.txt 
git commit -m "Add a.txt" -S 
touch b.txt 
git add b.txt 
git commit -m "Add b.txt" -S 
git filter-branch --index-filter 'git rm --cached --ignore-unmatch a.txt' --prune-empty HEAD 
git log --oneline --decorate 
b4efdf0 (HEAD -> master) iQIcBAABCgAGBQJVrvqHAAoJEGuo23L9/VuyntUQAIBD0g03rTKRkOd9eM4bJgUV jJezu7R4J0U+zVLrsrSl8oTrYrKPL5QAIqqaB9978qSx5WsmCJj8EfIZ2lwFj7kI sWWcqjAWcRjWrte/v7ehUyTpJF6h5mWJPbC31BueZ3qlVvvfI03NbMUGocm1VOvE KZakYkbhrA4ucA0K0YH9RKFo59cLS48SB7DQK4dBfdJSOnBC0Ga9pgBp8wnF2TQG znRA3MnGRPJMRxZsend5P6gyeGl3wo0J/yk8HDFZXudTRS3SLB+um3NcTXRLIE9Z Whud2oERKE9CuHU8Y64prbKKA27vWgaVQOC44ujaCqbYXuq+4Ozs34PBlf3CjJqW 19GdVBlqFfiyCPULwyxoPWkRk2kPQyEejt+sJIXG9QgefvoqFF5oLW/YA7AOrDSE luLbC8uxmTARCWGZVGINL7NmPmEVFDZVj9EyYOjxE/+0wm4cGNBHrL6/JMkVOgpT pWlgZWR3rX4IjzYtN6DMqKYNWVkVawZQUPh5n5jteuripWtnu5IG8vvvK2mtlkQ3 1OZIdQNAv0HYhBO0vHlV0o2TlVL5x9WfPFn+1XJepJUcoN3MdzXLxN27njdW5Bti olEqyHrTRxYJNZgSwpQ7WITheIFDqpdcoUV2h4hNjGcXfc0DfaevtCA/oQir+3L4 JlFB35Le9Yby9htVhlu2 =RJi9 -----END PGP SIGNATURE----- 
9f82e63 iQIcBAABCgAGBQJVrvp7AAoJEGuo23L9/Vuy/3QP/itaNGwRtlPB4uajGGHMUPxn gnzd5k5gaWvWlE0Cn/v+CFqE9zVfNiqfsEwJ5YUycUNtEuF9rsiqeQWaWdHWquqr kOEwRx/9mliK7iC2MZBn/biY5wBE2VcO2m281SnCKxslCjHJxlBo9rglq1t0wybT CX7C7ScKAtYkos4c1vL0D5Bam2panVXs/KT/YDgWZT9kTg+lEd7NaIwxxNn7HNs7 sOvI2zLyca2FepahF99ZRGg1kKXarVh9nW4mZ1GfeAUuCNSwgwBv+NO3wFC1Blcp uzKAo1F/cN0rAOr0bMdIZ0qJEVMBBpaqodqRqCOcmYTm5CoKFmcNJvixPl+hYsQx mPFxM0yVsjlLAnIckNqos/T3i6T8zrb5X4g5ZwuQZzzNKy1xx809v9erb2HHK+d1 +MqdzwEcMyGqfyhz9s1BGrwpBk5CAg2MXbtPpoMTBIG7hmke1al89jvgBiuir06E kEN6jl/2yAfsj7k5ryjFQNSPJ+HYEyvYBCx3u+xXdA5IBH6CU2S44RqugwztbVKz /Viel4wIHJ8UCA85ZiprRWJE+nz1RXKlBZc/37W4vcSUSTELXEkhaybOM/eBKACR sDHOKq5MG9VmZXcu0Zs0cyEvuqljSnZggbDasXHj68b86rB5VRGIO10ad1xKPnFZ PTUmKKtz1NZkMmjIX4vR =Mnxi -----END PGP SIGNATURE----- 

我有兩個問題。首先,爲什麼這不會從日誌中刪除第一次提交?第二,爲什麼PGP簽名現在位於提交消息的頂部,並且在使用git filter-branch時有什麼辦法可以避免這種行爲?

(在它的事項的情況下,我使用Git訴2.4.6)

回答

5

我沒有一個答案,爲什麼第一次提交還未從歷史中這個玩具示例中刪除。

但是,至於第二個問題,看起來這是設計狀態。當使用git filter-branch時,PGP簽名被故意中斷,以防止某人修改已簽名提交的內容,並使簽名提交的人看起來像簽名提交已修改的內容。

推測破碎的簽名也放在提交消息的頂部以引起對此事實的關注。

就我而言,由於所有簽名都以iQIcBA之類的內容開頭,因此我可以通過執行以下操作來刪除破損的簽名。

git filter-branch --msg-filter 'sed "/iQIcBA.*/,/.*END PGP SIGNATURE.*/d"' HEAD 

如果您想要提交提交,您可以執行以下操作。

git filter-branch --commit-filter 'git commit-tree -S "[email protected]"' HEAD 

然而,似乎簽署標籤而不是回溯簽署所有提交的優選(參見,例如here)。


這個答案是基於在幫助很大一部分來自雅各布·凱勒在git mailing list.

2

在回答你的第一個問題。該文件說:

雖然,此開關僅適用於有一個提交,只有一個父

https://git-scm.com/docs/git-filter-branch

這本質上是兩種說法。

  1. 提交必須有一個父代。
  2. 該提交不得有多個父代。

提交添加a.txt失敗的第一次檢查。

該代碼(由於文檔記錄不完整,原樣寫入)證實了這一點。

首先父字符串作爲參數傳遞給命令其上運行的每個傳遞承諾: https://github.com/git/git/blob/master/git-filter-branch.sh#L410

因爲沒有父母爲你的根犯這個是空的。因此,然後在後面的代碼中,我們有三個參數檢查test $# = 3發現這個情況並非如此: https://github.com/git/git/blob/master/git-filter-branch.sh#L47

所以移動到else分支在提交加入。

在有父提交的情況下,代碼進入第二個檢查測試"$1" = $(git rev-parse "$3^{tree}"),它比較前一個提交的樹的sha和該提交的樹的sha,如果它們是同樣的,它會跳過提交。

作爲一個方面說明,我真的希望這段代碼更具可讀性。這樣一個重大的項目允許這樣的提交是非常可悲的。再次,也許這只是我對SHELL的偏見。

我不知道爲什麼添加PGP簽名。這當然沒有記錄,所以我猜這是一個錯誤,鑑於閱讀代碼的困難,這並不奇怪。

+0

+1謝謝,很好的偵查! [郵件列表](http://marc.info/?l=git&m=143787385331380&w=2)上的人建議,PGP的東西不是一個錯誤,但是在設計上是爲了防止人們使它看起來像你簽名關閉您沒有實際簽名的更改。 –

+0

調查不用擔心。重新:郵件列表響應。這不是我讀過的。他說:「我不確定爲什麼它將第一行放在提交的頂部。」這對我說,他們也不認爲這是正確的。通過代碼判斷,我懷疑簽名通常存儲在提交消息中,但在運行'git log'時隱藏,除非添加'--show-signatures',但是當運行'filter'branch'時,他們忘記刪除它並將其添加到消息的正文中。我的猜測是編寫過濾器分支代碼的人不使用sigs。我會修補它,但代碼會傷害我的大腦。 – Gerry