Git Signoff 指定 Subkey 的配置方法


问题描述

在使用 GPG 签名 Git 提交时,如果配置了子密钥(Subkey),但 Git 仍然使用主密钥或其他子密钥进行签名。如何解决这个问题?

解决方案

查看密钥结构

首先查看你的 GPG 密钥结构:

1
gpg --list-secret-keys --keyid-format LONG

输出示例:

1
2
3
4
sec   rsa4096/0x1234567890ABCDEF 2024-01-01 [SCA]
ABCD1234ABCD1234ABCD1234ABCD1234ABCD1234
uid [ultimate] Your Name <your.email@example.com>
ssb rsa4096/0xFEDCBA0987654321 2024-01-01 [SEA]

其中 ssb 行显示的就是子密钥,记录其 Key ID(如 0xFEDCBA0987654321)。

强制指定子密钥

关键步骤:在密钥 ID 后添加叹号 ! 来强制 Git 使用指定的子密钥。

1
2
3
4
5
6
7
# 配置 Git 使用指定的子密钥(注意叹号)
git config --global user.signingkey 0xFEDCBA0987654321!

# 如果 shell 解释叹号,需要使用引号或转义
git config --global user.signingkey '0xFEDCBA0987654321!'
# 或者
git config --global user.signingkey 0xFEDCBA0987654321\!

为什么需要叹号?

根据 GitHub 官方文档和 GPG 的工作原理:

  1. GPG 的自动选择机制:当不指定叹号时,GPG 会自动选择一个”合适”的密钥进行签名。通常情况下,GPG 会优先使用最新创建的子密钥,如果没有合适的子密钥,则使用主密钥。

  2. 叹号的作用:叹号 ! 告诉 GPG “精确使用这个密钥,不要自动选择”。这可以确保 Git 始终使用你明确指定的子密钥。

  3. 实际场景:假设你有以下密钥结构:

    1
    2
    3
    sec   4096R/0x1234567890ABCDEF  [SCA]  (主密钥)
    ssb 4096R/0xAAAAAAAAAAAAAAAA [SEA] (子密钥 1,旧)
    ssb 4096R/0xFEDCBA0987654321 [SEA] (子密钥 2,新)

    如果你想使用旧的子密钥 1(0xAAAAAAAAAAAAAAAA),但不加叹号,GPG 很可能会使用新的子密钥 2。只有添加叹号才能强制使用指定的子密钥。

验证配置

1
2
3
4
5
6
# 查看 Git 配置
git config --global --get user.signingkey

# 测试提交并查看使用的密钥
git commit -S -m "Test commit"
git log --show-signature -1

在日志中,你应该看到类似这样的输出:

1
2
3
commit abc123...
gpg: Signature made Wed Mar 18 10:00:00 2026 CST
gpg: using RSA key FEDCBA0987654321

显示的密钥 ID 应该与你配置的子密钥一致。

常见问题

Git 使用了错误的密钥

症状:尽管配置了子密钥,Git 仍然使用主密钥或其他密钥签名。

解决方案

  1. 使用叹号强制指定
1
git config --global user.signingkey 0xFEDCBA0987654321!
  1. 清除缓存配置
1
2
git config --global --unset user.signingkey
git config --global user.signingkey 0xFEDCBA0987654321!
  1. 检查 GPG Agent 缓存
1
gpgconf --kill gpg-agent

GPG 提示”secret key not found”

症状:提交时 GPG 找不到指定的密钥。

解决方案

  1. 确认子密钥存在且可用:
1
gpg --list-secret-keys --keyid-format LONG
  1. 如果子密钥在智能卡上,确保卡片已插入且被识别:
1
gpg --card-status

总结

配置 Git 使用指定的 GPG 子密钥的关键是:在密钥 ID 后添加叹号 !

1
git config --global user.signingkey 0xSUBKEY_ID!

这样可以强制 Git 使用你指定的子密钥,而不是让 GPG 自动选择。

参考资源


文章作者: 2356
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 2356 !