TL;DR:匹配日期 + 重新创建 GPG 签名
(如果您知道剥离以保留 原始 签名的解决方法,请评论/编辑。)
我会碰到这个旧线程,因为已经引入了签名提交的功能,所有这些git filter-branch 和喜欢基本上都按照文档中的规定剥离签名:
...如果标签附加了签名,则签名将被剥离。根据定义,保留签名是不可能的。 ...(来源:--tag-name-filter )
但它也会破坏 GitHub 提交上漂亮的 Verified 徽章(如果以相同方式实现,则在其他 Git 托管位置),所以这也将解决这个问题。 部分。
Afaik 不可能通过git 命令破坏(GPG)签名,它也包含提交日期而不是签名日期in a simple way,因此甚至如果创作和提交的日期被移动,它仍然是当前日期,例如:
commit <hash>
gpg: Signature made Sun 25 Jul 2021 00:00:00 PM TZ
gpg: using TYPE key KEY
gpg: Good signature from "Signer <email@domain.tld>"
Author: Author <email@domain.tld>
AuthorDate: Sat Jan 1 00:00:00 2000 +0000
Commit: Author <email@domain.tld>
CommitDate: Sat Jan 1 00:00:00 2000 +0000
因此,假设您有一个要从某个提交签名的存储库(我会选择根提交;如果其他人在该存储库上工作,则不推荐)。 git commitsays 的文档也从环境变量中提取数据(如果存在),因此我们有一个地方可以输入。
要检索数据(可以使用git commit --date=... 设置),我们可以查看git show --format=%ad,因此对于原始日期字符串,可以:
git show --format=%ad --no-patch
# Sat Jan 1 00:00:00 2000 +0000
所以我们有:
- 起点
- 每个提交的原始日期字符串
-
GIT_COMMITTER_DATE 匹配日期(作者 -> 提交者)
对于变基,让我们这样做:
git rebase --root <branch-name> --keep-empty --interactive
这将用于分支<branch-name> 的根提交,保留使用git commit -m "empty" --allow-empty 创建的任何空提交,并询问您要修改哪些提交。在那里,您将所需的提交从 pick 更改为 edit(在我的情况下,将所有这些都标记为 edit),然后您将被放入一个分离的 HEAD 提交中,从这里开始乐趣开始。
# or "while :"
while true
do
GIT_COMMITTER_DATE=$(git show --format=%ad --no-patch) \
git commit --amend --gpg-sign --no-edit --allow-empty
git rebase --continue
done
(如果没有指定user.signingkey,请使用--gpg-sign=<fingerprint>)
这将遍历每个edit-marked 提交,设置提交者的日期以匹配作者的日期,保留任何空提交,不会触及整个补丁主体,并将添加带有日期的签名命令已执行。
看到fatal: No rebase in progress? 后,按Ctrl-C 停止循环并检查日志以确认日期匹配并且签名随处可见:
git log --pretty=fuller --show-signature
如果日志中一切正常,只需发出 git push --force 即可。现在您应该会看到每个提交的 Verified 徽章。
Example with a real history tree。 GitHub 似乎并不关心签名的日期(任何地方都没有参考),但它仍然会出现在 git log 中。