一、使用 GPG 对 Git 提交进行签名
- 普通的 Git 提交虽然包含作者、邮箱、时间戳等元数据,但这些信息可以被轻易伪造,缺乏密码学层面的身份认证
- GPG 签名可以对提交内容进行加密签名,用于证明该提交是由持有对应私钥的开发者签名,并且提交内容在签名后未被篡改
- GitHub、GitLab 等平台可以对提交签名进行校验并显示验证状态,从而提升代码来源的可信度
二、在 Git 配置中配置 GPG 信息
NOTE如果还未安装 GPG 程序,可以查阅文章 GnuPG 安装以及基础配置说明 进行安装
2.1 配置 GPG 程序
在默认情况下 windows 和 macOS 可能存在找不到 gpg 可执行文件,因此可以显式的指定 gpg 程序的位置
2.2 确认用于 Git 提交签名的 GPG 子密钥信息
NOTE如果还未生成 GPG 密钥,可以查阅文章 GPG 安全密钥管理最佳实践 进行生成
列出本地主密钥及其子密钥完整指纹(本实例采用主密钥隔离):
gpg --list-secret-keys --with-subkey-fingerprints --keyid-format=LONG示例输出:
sec ed25519/F9904AD5C93B705A 2025-09-09 [C] [expires: 2030-09-08] C5D403FBDEDF67791962A393F9904AD5C93B705Auid [ultimate] user <user@admin.com>ssb ed25519/AC3897D449CE8390 2025-09-09 [S] [expires: 2026-09-08] A385D5291681E2F0FCF5EBA8AC3897D449CE8390ssb cv25519/92F1AB15A1AD51AF 2025-09-09 [E] [expires: 2026-09-08] BA0D1623D1EDFBAFB02D966792F1AB15A1AD51AF如输出所示:
- 主密钥具备 认证 [C] 能力,子密钥分别具备 签名 [S] 能力、加密 [E] 能力
- 主密钥密钥指纹:
C5D403FBDEDF67791962A393F9904AD5C93B705A,Long Key Id:F9904AD5C93B705A - 签名子密钥指纹:
A385D5291681E2F0FCF5EBA8AC3897D449CE8390,Long Key Id:AC3897D449CE8390 - 加密子密钥指纹:
BA0D1623D1EDFBAFB02D966792F1AB15A1AD51AF,Long Key Id:92F1AB15A1AD51AF
如果未采用主密钥隔离的方式,按照 GPG 的默认密钥生成策略,主密钥通常同时具备 签名 [S] 和 认证 [C] 能力
复制具备 签名 [S] 能力的密钥的指纹内容
2.3 配置 Git 使用密钥
使用具备 签名 [S] 能力的密钥指纹,配置 Git 提交签名
全局配置(影响后续创建的所有仓库)
git config --global user.signingkey A385D5291681E2F0FCF5EBA8AC3897D449CE8390git config --global commit.gpgsign true单个仓库配置(覆盖全局)
cd path/to/repogit config --local user.signingkey A385D5291681E2F0FCF5EBA8AC3897D449CE8390git config --local commit.gpgsign true关闭配置
启用全局签名后,所有 Git 提交将默认进行签名 如果某个仓库不需要使用 GPG 签名,可以在该仓库中单独关闭:
git config --local commit.gpgsign false如果后续不再使用 GPG 对 Git 提交进行签名,也可以全局关闭:
git config --global commit.gpgsign false三、创建 Git 仓库测试
3.1 测试 GPG 签名
echo "test" | gpg --clearsign- 成功弹出 Pinentry 输入密码(或从命令行输入),并生成签名输出,则配置正确
- 在无 GUI 环境中,可能需要配置
pinentry-tty或gpg-agent才能正常输入口令
3.2 测试 Git commit 签名
# 创建并初始化项目mkdir test && cd testgit init
## 配置仓库信息git config --local user.name usergit config --local user.email user@admin.com
# 启用 gpg 签名git config --local user.signingkey A385D5291681E2F0FCF5EBA8AC3897D449CE8390git config --local commit.gpgsign true
# 创建文件并提交touch testgit add testgit commit -S -m "test commit" # 在已开启 commit.gpgsign 的情况下,-S 参数是可选的,此处显式添加仅用于强调该提交是签名提交此时输入密钥的密码完成签名操作,使用以下命令查看 Git 提交记录并调用 GPG 验签并打印结果
git log --show-signature -1示例输出:
commit 1c3059eb547bdaa4f1726a611eec3c4245007269 (HEAD -> master)gpg: Signature made Tue Sep 3 20:16:27 2025 CSTgpg: using EDDSA key A385D5291681E2F0FCF5EBA8AC3897D449CE8390gpg: Good signature from "user <user@admin.com>" [ultimate]Author: user <user@admin.com>Date: Tue Sep 3 20:16:27 2025 +0800
test commitNOTEGit 默认不会对提交进行签名验证
只有在显式指定--show-signature或使用verify-commit时才会调用 GPG 进行验签
四、在 GitHub 配置 GPG 信息
4.1 上传 GPG 公钥
-
导出 GPG 公钥
Terminal window gpg --armor --export "你的邮箱、密钥指纹或是 Long Key Id" > public_key.asc -
登录 Github 后点击 Settings → SSH and GPG keys → GPG keys 或直接访问 https://github.com/settings/keys
-
在 GPG keys 区域点击 New GPG key
-
将
public_key.asc文件中的内容完整复制并粘贴到文本框中,并进行命名 -
点击 Add GPG key 完成添加
上传成功后,GitHub 会显示该 GPG Key 的 Key ID / 指纹 以及绑定的邮箱信息
4.2 验证 GitHub 上的提交签名状态
将本地已签名的提交推送到 GitHub后,在仓库的 Commits 页面中查看验证情况:
-
如果提交旁显示 Verified,说明:
- 提交已正确使用 GPG 签名
- 签名校验通过
- 提交作者邮箱与 GPG 公钥 UID 邮箱匹配
-
如果显示 Unverified 或没有标识,通常需要检查:
- 是否推送的是已签名的提交
git commit时是否启用了 GPG 签名- 提交使用的邮箱是否与 GPG Key 中的邮箱一致
- GitHub 账户中是否已添加对应的 GPG 公钥
4.3 常见导致 GitHub 不显示 Verified 的原因
- 提交未实际签名(未开启
commit.gpgsign,或未使用-S) user.signingkey指向了错误的密钥(如非签名子密钥)- 提交作者邮箱与 GPG 公钥 UID 邮箱不一致
- 使用了不同机器提交,但未导入对应的私钥
- 使用了过期或已被 GitHub 标记为无效的密钥
4.4 验证已存在提交的签名信息
即使 GitHub 未显示 Verified,也可以在本地确认提交是否真实签名:
git log --show-signature -1如果本地显示 Good signature,说明签名本身是正确的,问题通常出在 GitHub 侧的邮箱或公钥配置上
非商业用途可以使用,但必须注明出处;
若有改编需采用相同许可协议发布。