您可以 GPG 签署旧提交吗?

Mag*_*nus 163 git

Git 现在能够使用 签署提交git commit -S,这很棒,但有时我忘记了标志commit,有时我将我申请的补丁邮寄给自己am,并且该命令没有签名标志。

有没有办法为已经记录的提交添加签名?

Shu*_*ary 171

  1. 进入交互式 rebase 模式。
  2. 在您要签名的每个提交之后添加以下行

    exec git commit --amend --no-edit -S

这将在选择每个提交后运行此命令。

更新:

更简单的方法是:

git rebase --exec 'git commit --amend --no-edit -n -S' -i development
Run Code Online (Sandbox Code Playgroud)

这会在开发(或任何哈希)之前重新设置所有内容,并且您不必在每次提交后复制粘贴。

  • 这不会改变历史,需要`git push --force`吗? (23认同)
  • 根本没有理由变基。只需运行`git commit --amend --no-edit -n -S`。 (3认同)
  • @BarryMode 人们是正确的,因为你不能放弃旧的提交。从技术上讲,这个答案不会放弃旧的提交,而只是创建一个包含相同内容和附加签名的新提交。这与需要强制推送的提交不同。 (3认同)
  • 哦,我希望我早点找到这个。我读了很多东西,甚至是从 GitHub 自己那里读到的,说你不能放弃旧的提交。这证明完全是假的!我本可以保存数百个提交,现在我已经压缩了。哦哦。。。谢谢分享!我用这个做了一个别名。`resign = "!re() { git rebase --exec 'git commit --amend --no-edit -n -S' -i $1; }; re"` 变成了 `git resign HASH` (2认同)
  • 这应该是常识!你为人类做出了伟大的贡献(没有讽刺!)! (2认同)

小智 52

签署一个提交会改变它的内容,所以最近的提交会改变它们的哈希值。

如果您只想签署最近的提交,git commit -S --amend将起作用。

  • 大多数时候,签署最近的提交,甚至在其之上创建一个空的签名提交就足以保证真实性。Git 提交是一棵 Merkle 树,因此修改任何祖先提交都需要重写其后代,从而使签名无效。 (4认同)
  • 我想这里的许多用户都希望在“git-filter-repo”删除所有提交后保留除提交 SHA 之外的提交元数据。 (2认同)

Ill*_*tor 20

我使用git rebase -i --root(请参阅重写历史记录)并更改pickedit.

然后我为每个提交使用git commit -S --amend --no-edit && git rebase --continue (在 Windows 上)

这是为每个提交手动签名。我希望我们能找到更好的解决方案。


小智 14

如果您需要 GPG 签署自当前分支上的特定提交以来的所有提交,您可以使用以下代码:

git filter-branch --commit-filter 'git commit-tree -S "$@";' <COMMIT>..HEAD
Run Code Online (Sandbox Code Playgroud)

<COMMIT>提交 ID在哪里(例如abc123e5)。

这有一个额外的好处,它不会干扰提交元数据(包括提交日期)。但是,提交哈希会改变(因为它是每个提交内容的摘要,并且每个提交都会添加一个签名)。

如果您还想停止在每次提交时提示您输入 GPG 密码,请参阅此答案:https : //askubuntu.com/a/805550

注意:从 切换gpggpg2GIT 签名将需要您在 GPG 2 中重新导入您的私钥。


小智 9

我也偶然发现了同样的问题,这是我的解决方案:

git rebase -i --root --exec 'git commit --amend --no-edit --no-verify -S'
Run Code Online (Sandbox Code Playgroud)

这将签署我第一次初始提交的所有提交,并绕过我使用husky设置的提交钩子无需更改pickedit.

  • 这会修改提交日期。提交日期设置为当前时间。 (6认同)

小智 7

如果不需要对提交进行过滤,那么最好使用 rebase 而不是 filter-branch:

git rebase -i master --exec 'git commit --amend --no-edit --no-verify -S --reset-author'
Run Code Online (Sandbox Code Playgroud)

否则,您可以保持不属于您的提交不变。
设置以下别名~/.gitconfig(替换your@address.com为您的电子邮件地址):

resign = "!_() { : git checkout ; [ \"$#\" -eq 0 ] && echo 'Usage: resign <rev-list>' && exit 2; \
                   git filter-branch --commit-filter ' \
                   if [ \"$GIT_COMMITTER_EMAIL\" = \"your@address.com\" ]; then git commit-tree -S \"$@\"; else git commit-tree \"$@\"; fi' $1; }; _"
Run Code Online (Sandbox Code Playgroud)

例如,要放弃从 master 拉取的当前分支中的所有提交,请执行以下操作:

git resign master..
Run Code Online (Sandbox Code Playgroud)

归功于 BarryModeRoberto Leinardi之前的回答


Rob*_*rdi 6

如果您只想过滤特定的提交并仅对它们进行签名,您可以使用filter-branch

git filter-branch --commit-filter 'if [ "$GIT_COMMITTER_EMAIL" = "user@domain.com" ];
  then git commit-tree -S "$@";
  else git commit-tree "$@";
  fi' HEAD
Run Code Online (Sandbox Code Playgroud)

如果出于某种原因,您只想签署自己的提交,这将非常有用。