跳到主要内容
ecdsa.com
Git (commit -S, tag -s, commit.gpgsign) with GnuPGGit

错误信息

error: gpg failed to sign the data

也可能输出为

  • fatal: failed to write commit object
  • gpg: skipped "ABCDEF0123456789": No secret key
  • gpg: signing failed: No secret key

Git 会在第一行之后打印 gpg 的 stderr,例如“gpg: skipped "<key>": No secret key”或“gpg: signing failed: Inappropriate ioctl for device”。如果 `gpg.program` 无法启动,Git 会打印“(no gpg output)”。

含义

Git 请求 GnuPG 对提交或标签对象签名,gpg 以错误退出,于是 Git 中止了操作(“fatal: failed to write commit object”)。Git 自己输出的这一行没有说明原因;与它一起打印的 gpg 输出行(或 `[GNUPG:]` 状态行)才会说明。最常见的是“No secret key”:配置的 `user.signingkey` 在当前密钥环中不存在。

原因

修复方法

  1. 1.

    用配置的密钥手动运行 gpg

    如果用同一把密钥执行 `gpg --clearsign` 也失败,问题就出在 GnuPG 而不是 Git——它给出的消息才是真正的错误信息。

    bash
    git config --get user.signingkey
    gpg --list-secret-keys --keyid-format=long          # is that key listed, with a "sec" line?
    echo test | gpg --clearsign --local-user "$(git config --get user.signingkey)" > /dev/null && echo "gpg can sign"
  2. 2.

    让 Git 指向已有的密钥,并让 pinentry 正常工作

    使用本地已有私钥的长密钥 ID 或指纹,显式设置 `gpg.program`,并在 shell 中导出 `GPG_TTY`。

    bash
    KEY=$(gpg --list-secret-keys --with-colons alice@example.com | awk -F: '/^sec/ {print $5; exit}')
    git config --global user.signingkey "$KEY"
    git config --global gpg.program "$(command -v gpg)"
    export GPG_TTY=$(tty)        # in ~/.bashrc / ~/.zshrc, so pinentry can ask for the passphrase

相关错误

浏览完整的签名错误库