请考虑以下示例。
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 v.2.4.6。)
答案 0 :(得分: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 "$@"' HEAD
但是,似乎首选签名而不是追溯签署所有提交(请参阅例如,here)。
这个答案很大程度上取决于雅各布凯勒对git
mailing list.
答案 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签名。它肯定没有记录,所以我猜这是一个错误,考虑到阅读代码的难度,这并不奇怪。