gpg签名数据失败 致命错误:无法写入提交对象 [Git 2.10.0]

719

我阅读了关于pretty属性在Git 2.10版本发布说明中的几篇文章。通过阅读这些文章,将git升级到2.10.0,并对全局.gitconfig进行了更改,结果如下 -

[filter "lfs"]
    clean = git-lfs clean %f
    smudge = git-lfs smudge %f
    required = true
[user]
    name = xyz
    email = abc.def@gmail.com
    signingkey = AAAAAAA
[core]
    excludesfile = /Users/xyz/.gitignore_global
    editor = 'subl' --wait
[difftool "sourcetree"]
    cmd = opendiff \"$LOCAL\" \"$REMOTE\"
    path = 
[mergetool "sourcetree"]
    cmd = /Applications/SourceTree.app/Contents/Resources/opendiff-w.sh \"$LOCAL\" \"$REMOTE\" -ancestor \"$BASE\" -merge \"$MERGED\"
    trustExitCode = true
[alias]
    lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
[color "diff"]
    old = red strike
    new = green italic

但现在我尝试使用签署我的提交的方式

git commit -a -S -m "message"

我看到了以下错误信息 -

您需要输入密码来解锁用户“XYZ(数字签名)”的秘密密钥

2048位RSA密钥,ID为AAAAAAAA,创建于2016年07月01日

错误:gpg无法签署数据致命错误:无法编写提交对象

注意 - 我仍然可以使用git commit -a -m“message”提交更改 有没有办法克服这个问题?或者需要在gpg配置中进行任何更改以适应git的升级?

更新 1

在阅读Is there a way to "autosign" commits in Git with a GPG key?之后,我希望进一步提高其实用性。我已经使用配置了密钥。

git config --global user.signingkey ED5CDE14(with my key) 
git config --global commit.gpgsign true

很明显,无论如何都会出现相同的错误。


5
我遇到了类似的问题。我在Windows上卸载了Git 2.8(git-scm),然后安装了2.10版本。现在每次使用“-S”命令时都会出现“gpg failed to sign the data”的错误提示。在2.8版本中,我可以顺利地签署提交记录,但现在不知道出了什么问题。 - Illuminator
11
添加 user.signingkey 解决了我的问题,很奇怪。 - Xavier Ho
3
有点讽刺的是,我更换了电脑重新设置一切,结果却在寻找自己的问题时发现没有一个建议的解决方案足够简单干净,可以让我轻松开始。 - Naman
60
尝试运行 gpgconf --kill gpg-agent 命令,详情请见此处讨论 - Lounge9
17
请确保 git config --get-all user.namegit config --get-all user.email 与用于签名的密钥相同,可以通过 gpg -K --keyid-format SHORT 进行检查。 - Max Vorobjev
显示剩余10条评论
51个回答

941

我在 macOS 上遇到了这个问题。

原始回答:

似乎 gpg(brew 的更新)将 gpg 的位置更改为 gpg1,您可以更改 git 查找 gpg 的二进制文件:

git config --global gpg.program gpg1

如果您没有 gpg1: brew install gpg1

更新的答案:

看起来 gpg1 已经被弃用/"轻轻地推出使用", 所以您可能实际上需要升级到 gpg2,不幸的是这涉及到更多步骤/需要一定的时间:

brew upgrade gnupg  # This has a make step which takes a while
brew link --overwrite gnupg
brew install pinentry-mac
echo "pinentry-program $(brew --prefix)/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf
killall gpg-agent

第一部分安装gpg2,后面是使用它所需的一个hack。如需故障排除,请参见此答案(尽管它是关于Linux而不是Brew),它建议进行一个很好的测试:

echo "test" | gpg --clearsign  # on linux it's gpg2 but brew stays as gpg

如果这个测试成功(没有错误/输出包含PGP签名),则您已经成功更新到最新的gpg版本。
现在,您应该能够再次使用git签名!需要注意的是,您需要拥有:
git config --global gpg.program gpg  # perhaps you had this already? On linux maybe gpg2
git config --global commit.gpgsign true  # if you want to sign every commit

注意:在运行签名提交后,您可以使用以下方式验证其是否已签名:
git log --show-signature -1

这将包括最后一次提交的 gpg 信息。


9
将 gpg.program 设置为 /usr/local/bin/gpg(不要添加“1”)对我起了修复作用。 - Iskar
8
嗯...不起作用。在Xcode登录时仍然出现错误。 - Albert T. Wong
125
最终解决了我的问题:"killall gpg-agent && gpg-agent --daemon --use-standard-socket --pinentry-program /usr/local/bin/pinentry" - Dan Bechard
12
只有当我使用短密钥ID时才能正常工作: git config --global user.signingkey <short Key ID> - Mohamed Hashem
12
在 M1 Mac 上,命令行应该是 echo "pinentry-program /opt/homebrew/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf - Saifur Rahman Mohsin
显示剩余29条评论

750

48
如果使用鱼壳,请在您的个人配置文件中添加“set -x GPG_TTY (tty)”来设置GPG_TTY。 - fasfsfgs
@StuartCardall chown命令有什么意义?通常情况下,当您登录或创建伪终端时,系统进程已经将其分配给您。如果它归其他人所有且您不是root,则会失败。如果组是其他内容,则可能无关紧要,并且用户通常不会在tty组中。 - poolie
20
我已经将这个变量添加到了 ~/.zshrc 文件中,现在它正确地连接到终端,我又可以提交了。非常感谢您的帮助! - Alex Gurrola
20
这是我需要的WSL2所需的东西。 - Theodore R. Smith
16
使用启用了Instant Prompt的Powerlevel10k的zsh用户要注意,可能会遇到not a tty值:https://unix.stackexchange.com/a/608921/5095。一个快速的解决方法是只需使用一个更快且在Zsh环境中更安全的命令:`export GPG_TTY=$TTY`。 - Igor Klimer
显示剩余9条评论

476

GIT_TRACE=1 显示 Git 正在执行的实际操作:

$ GIT_TRACE=1 git commit -m "example commit message"
20:52:58.902766 git.c:328               trace: built-in: git 'commit' '-vvv' '-m' 'example commit message'
20:52:58.918467 run-command.c:626       trace: run_command: 'gpg' '--status-fd=2' '-bsau' '23810377252EF4C2'
error: gpg failed to sign the data
fatal: failed to write commit object

现在手动运行失败的命令:

$ echo "dummy" | gpg -bsau 23810377252EF4C2
gpg: skipped "23810377252EF4C2": Unusable secret key
gpg: signing failed: Unusable secret key

结果发现我的密钥已经过期了,git 并不是罪魁祸首。


15
这实际上帮助我解决了自己的问题,并且它是适用于所有此状态消息问题的解决方案。 +1 - xHocquet
5
谢谢!这导致了我的问题。很奇怪的是,在一个项目中,我的本地.git/config文件中指定了一个与我的签名电子邮件不匹配的name,这足以拒绝它。 - kross
28
在我的电脑上执行“gpg -bsau <key>”并没有执行任何操作。这是因为执行时间过长吗?或者这意味着该密钥可以正常使用?@VonC 有什么见解吗? - Naman
14
如果您的密钥已过期,您可以按照此处的说明进行续订:https://dev59.com/TVgR5IYBdhLWcg3wp-u5#43728576 - Constablebrew
7
这是唯一正确的答案。了解发生了什么比盲目尝试一百万种不同的可能解决方案要好。 - Samie Bencherif
显示剩余14条评论

230

请按照以下步骤设置签名提交: https://help.github.com/en/articles/telling-git-about-your-signing-key

如果仍然出现以下错误消息: gpg failed to sign the data fatal: failed to write commit object

这不是 Git 的问题,而是与 GPG 有关,请按照以下步骤操作:

  1. gpg --version
  2. echo "test" | gpg --clearsign

如果显示:

gpg: signing failed: Inappropriate ioctl for device
gpg: [stdin]: clear-sign failed: Inappropriate ioctl for device

  1. 然后使用export GPG_TTY=$(tty)

  2. 再次尝试echo "test" | gpg --clearsign,以获取PGP签名。

  3. git config -l | grep gpg

gpg.program=gpg
commit.gpgsign=true
  1. 应用git commit -S -m "提交信息"

32
“export GPG_TTY=$(tty)”是解决的关键。我把它加到了我的“.zshrc”文件里。 - Shane Stillwell
3
使用Ubuntu 20.04成功了。谢谢!这不是第一个提供export GPG_TTY=$(tty)的答案。区别在于@jayesh还提供了一个测试,而且没有涉及与Ubuntu无关的gpg2、fish或brew。这也是一个更新的答案,就我而言,这意味着此刻这个答案可能比那些几年前的更好。因此,这篇简短、有效和最新的发帖做得很好。 - TonyG
2
我确认这在WSL2上可行!在Git Bash中,我不需要进行此配置,即GUI自然出现。但是,在WSL2中,尽管通过X服务器支持GUI,但没有export GPG_TTY=$(tty)仍无法正常工作。这个方法非常有效。 - Param Siddharth
通过 export GPG_TTY=$(tty) 指令解决了问题!在 Kali ARM 5.4.83-Re4son-v7l+gpg (GnuPG) 2.2.27 上进行了确认。 - Kamil Gierach-Pacanek
2
救了我的一天(和夜晚)。你能告诉我 export GPG_TTY=$(tty) 的意思吗? - Aji Saputra Raka Siwi
显示剩余2条评论

172
我已经通过这个简短易行的方法完成了它:
在macOS上自动签署提交(全局和不同的IDE):
这种方式获取您的signingkey
brew install gnupg gnupg2 pinentry-mac
git config --global user.signingkey <YOUR_SIGNING_KEY>
git config --global commit.gpgsign true
git config --global gpg.program gpg

将以下内容放入gpg.conf文件中(使用nano ~/.gnupg/gpg.conf命令编辑文件):
no-tty

请将以下内容放入 gpg-agent.conf 文件中(使用 nano ~/.gnupg/gpg-agent.conf 命令编辑文件):
pinentry-program /usr/local/bin/pinentry-mac

更新:

根据评论中的建议,在编辑配置文件 gpg.conf 后,您可能需要执行 killall gpg-agent 命令。不用说,这个命令将终止 GPG (Gnu 隐私保护)代理。


4
你能解释一下这些命令是做什么的吗?这会有助于理解。 - Just The Highlights
22
在设置配置文件后,我还必须运行“killall gpg-agent”,然后才能使其正常工作! - Pasukaru
我们如何知道我们可以信任pinentry-mac背后的人?我不是说我们不能,但GPGTools组织由一个非常小的团队支持,而且该存储库仅有5个贡献者,相比之下,使用brew install gnupg利用了https://gnupg.org/的工作。 - sunknudsen
1
如果有帮助到其他人,我的问题是我设置了一个无效的本地 user.signingkey,我没有在我的sourcetree配置中注意到它,也没有在我的全局设置中注意到(因为我没有想到去查看本地配置)。确保本地 (git config --local --get user.signingkey) 和全局 (git config --global --get user.signingkey) 是相同的,或者最好的方法是,如果它是无效的,取消设置本地的(git config --local --unset user.signingkey)。 - Glenn 'devalias' Grant
13
在使用原生brew的Apple Silicon上,pinentry-mac的路径将会是/opt/homebrew/bin/pinentry-mac - David Gay
显示剩余4条评论

119

可能有助于结束进程 gpg-agent ,因为它可能会陷入旧数据无法处理的状况。这样,重新启动的新 gpg-agent 将会要求输入密码。


38
使用命令 gpg-agent --daemon 启动它。 - FooBar
3
我需要重新启动gpg-agent。 - GnrlBzik
36
在 macOS 上终止进程的命令为:killall gpg-agent - incleaf
10
在Ubuntu上,运行命令gpgconf --kill gpg-agent可以停止GPG代理。 - Adam
对于Mac用户:一旦gpg-agent被终止,运行提交命令会要求输入密码...为了不重复相同的步骤,请确保将密码添加到Mac钥匙串中。 - Lalit Mehra

53
对于在MacOS机器上遇到此问题的任何人,请尝试以下操作:
1. `brew uninstall gpg` 2. `brew install gpg2` 3. `brew install pinentry-mac`(如果需要) 4. 使用算法创建密钥:`gpg --full-generate-key` 5. 通过执行以下命令获取生成的密钥:`gpg --list-keys` 6. 在此处设置密钥:`git config --global user.signingkey <从列表中获取的密钥>` 7. `git config --global gpg.program $(which gpg)` 8. `git config --global commit.gpgsign true` 9. 如果您想将密钥导出到GitHub,则执行以下操作:`gpg --armor --export <密钥>`,并将此密钥添加到GitHub的GPG密钥中:https://github.com/settings/keys(包括START和END行) 如果问题仍然存在:

test -r ~/.bash_profile && echo 'export GPG_TTY=$(tty)' >> ~/.bash_profile

echo 'export GPG_TTY=$(tty)' >> ~/.profile

如果问题仍然存在:

安装https://gpgtools.org并通过菜单栏中的Key->Sign按键对您使用的密钥进行签名。

如果问题仍然存在:

前往:‎⁨全局.gitconfig文件,我的情况下位于:‎⁨/Users/gent/.gitconfig 并修改.gitconfig文件 (请确保电子邮件和姓名与生成密钥时所创建的相同)

[user]
    email = gent@youremail.com
    name = Gent
    signingkey = <YOURKEY>
[gpg]
    program = /usr/local/bin/gpg
[commit]
    gpsign = true
    gpgsign = true
[filter "lfs"]
    process = git-lfs filter-process
    required = true
    clean = git-lfs clean -- %f
    smudge = git-lfs smudge -- %f
[credential]
    helper = osxkeychain

2
在 .gitconfig 中添加 'gpsign = true' 对我来说解决了这个问题。 - Pierre
我不得不运行 'gpg-agent --daemon',这对我解决了问题(OS X,brew)。 - James Young
对于 Windows 上的 Github 客户端,它可以工作!在配置并添加了 gpg 密钥(在 git bash 中)之后,您必须将 gpg 添加到 git 配置中的 program = C:\Program Files\Git\usr\bin\gpg.exe 路径;您可以在 https://gist.github.com/xavierfoucrier/c156027fcc6ae23bcee1204199f177da 找到详细信息。 - Sergio Perez
对于 Windows 上的 Github 客户端,它是有效的!在配置和添加 GPG 密钥(在 git bash 中)之后,您需要将 gpg 添加到 git 配置中的 program = C:\Program Files\Git\usr\bin\gpg.exe 路径中;您可以在 https://gist.github.com/xavierfoucrier/c156027fcc6ae23bcee1204199f177da 上找到详细信息。 - undefined
“signingkey” 是我缺少的部分。因为我没有这个,它使用了我的配置文件中的姓名和电子邮件。我运行了 gpg --list-secret-keys --keyid-format=long 命令来获取我的签名密钥(在 sec 行后面的字母数字字符序列)。然后我运行了 git config --global user.signingkey <signingkey> 命令,将 <signingkey> 替换为我在第一步中获得的内容,现在我的提交已经被签名了。 - Samuel Slade
1
工作得非常完美。这应该被接受为正确答案。 - Ani

46

我在这里提供个人意见:

当您创建并添加一个密钥到gpg-agent时,您定义了一个称为“密码短语”的东西。现在,“密码短语”在某个时间点会过期,gpg需要您再次输入它以解锁您的密钥,以便您可以开始签名。

当您使用任何其他与

其中一种解决方案是使用gpg --sign a_file.txt,然后输入您创建密钥时输入的密码短语,然后一切都应该没问题(应该自动签名)。

请参阅此答案,了解如何为您的密码短语设置更长的超时时间,以便您不必一直这样做。

或者,您可以使用ssh-keygen -p完全删除密码短语。

编辑:执行man gpg-agent以阅读有关如何自动执行上述操作的内容,并添加以下行

GPG_TTY=$(tty)
export GPG_TTY

如果你使用的是bash, 在你的.bashrc文件中添加内容,或重新登录以使其生效。


这解决了我的问题。在某处建议使用 GIT_TRACE=1 git commit 并没有提供任何有用的信息,因此很难弄清楚问题所在。 - evgeni tsvetanov

36

我看到过类似的答案,但没有完全符合我所需要的。在Linux上,我需要使用以下命令杀死并重新启动我的gpg-agent

$ pkill gpg-agent
$ gpg-agent --daemon
$ git commit ...

这对我起作用了。从其他评论中得知,看起来确实需要将user.signingkey设置为您的私钥。

$ git config --global user.signingkey [your_key_hash]

2
这个方法在我使用的MacOS 10.15.6上有效,我安装了来自brew的gpg(GnuPG)2.2.23。感谢您的提示! - Jimmie Tyrrell
这个签名密钥是从哪里来的?GitHub/CodeCommit等? - Jamie Hutber
@JamieHutber 你需要创建自己的签名密钥并将其添加到GitHub。你可以在这里查看GitHub文档:https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent - Engineero
我没有意识到你需要将它们添加到Github...明白了。不过我正在使用AWS上的CodeCommit。 - Jamie Hutber
@JamieHutber,应该有一种方法可以将密钥添加到AWS中。您可以按照类似的说明进行创建,然后需要与管理员合作或在网上搜索以找出如何将其添加到AWS配置文件中。我对这个设置不是很熟悉。 - Engineero
显示剩余4条评论

28

每次在我的macOS上注销然后重新登录时,我都会遇到这个错误。解决方案只需要运行一个简单的单个命令:

我每次注销再登录就会出现这个错误,只需要运行一个简单的命令即可解决:

killall gpg-agent

我认为这只是gpg代理的一个错误,将其杀死然后再次运行即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接