1462 字
7 分钟
使用 GPG 对 Git 提交进行签名

一、使用 GPG 对 Git 提交进行签名#

  • 普通的 Git 提交虽然包含作者、邮箱、时间戳等元数据,但这些信息可以被轻易伪造,缺乏密码学层面的身份认证
  • GPG 签名可以对提交内容进行加密签名,用于证明该提交是由持有对应私钥的开发者签名,并且提交内容在签名后未被篡改
  • GitHub、GitLab 等平台可以对提交签名进行校验并显示验证状态,从而提升代码来源的可信度

二、在 Git 配置中配置 GPG 信息#

NOTE

如果还未安装 GPG 程序,可以查阅文章 GnuPG 安装以及基础配置说明 进行安装

2.1 配置 GPG 程序#

在默认情况下 windows 和 macOS 可能存在找不到 gpg 可执行文件,因此可以显式的指定 gpg 程序的位置

  • windows

    Terminal window
    # 注意:路径中包含空格时,需要使用双引号包裹。示例路径为 gpg4win 的默认安装路径
    git config --global gpg.program "C:/Program Files/Gpg4win/bin/gpg.exe"
  • macOS#

    Terminal window
    # 示例路径为通过 Homebrew 安装 GnuPG 的默认安装路径
    git config --global gpg.program "/opt/homebrew/bin/gpg"
  • Linux#

    通常不需要额外配置,Git 会自动找到系统 GPG。如果遇到问题,可以类似指定路径。

2.2 确认用于 Git 提交签名的 GPG 子密钥信息#

NOTE

如果还未生成 GPG 密钥,可以查阅文章 GPG 安全密钥管理最佳实践 进行生成

列出本地主密钥及其子密钥完整指纹(本实例采用主密钥隔离):

Terminal window
gpg --list-secret-keys --with-subkey-fingerprints --keyid-format=LONG

示例输出:

sec ed25519/F9904AD5C93B705A 2025-09-09 [C] [expires: 2030-09-08]
C5D403FBDEDF67791962A393F9904AD5C93B705A
uid [ultimate] user <user@admin.com>
ssb ed25519/AC3897D449CE8390 2025-09-09 [S] [expires: 2026-09-08]
A385D5291681E2F0FCF5EBA8AC3897D449CE8390
ssb cv25519/92F1AB15A1AD51AF 2025-09-09 [E] [expires: 2026-09-08]
BA0D1623D1EDFBAFB02D966792F1AB15A1AD51AF

如输出所示:

  • 主密钥具备 认证 [C] 能力,子密钥分别具备 签名 [S] 能力、加密 [E] 能力
  • 主密钥密钥指纹:C5D403FBDEDF67791962A393F9904AD5C93B705ALong Key IdF9904AD5C93B705A
  • 签名子密钥指纹:A385D5291681E2F0FCF5EBA8AC3897D449CE8390Long Key IdAC3897D449CE8390
  • 加密子密钥指纹:BA0D1623D1EDFBAFB02D966792F1AB15A1AD51AFLong Key Id92F1AB15A1AD51AF

如果未采用主密钥隔离的方式,按照 GPG 的默认密钥生成策略,主密钥通常同时具备 签名 [S]认证 [C] 能力

复制具备 签名 [S] 能力的密钥的指纹内容

2.3 配置 Git 使用密钥#

使用具备 签名 [S] 能力的密钥指纹,配置 Git 提交签名

全局配置(影响后续创建的所有仓库)#

Terminal window
git config --global user.signingkey A385D5291681E2F0FCF5EBA8AC3897D449CE8390
git config --global commit.gpgsign true

单个仓库配置(覆盖全局)#

Terminal window
cd path/to/repo
git config --local user.signingkey A385D5291681E2F0FCF5EBA8AC3897D449CE8390
git config --local commit.gpgsign true

关闭配置#

启用全局签名后,所有 Git 提交将默认进行签名 如果某个仓库不需要使用 GPG 签名,可以在该仓库中单独关闭:

Terminal window
git config --local commit.gpgsign false

如果后续不再使用 GPG 对 Git 提交进行签名,也可以全局关闭:

Terminal window
git config --global commit.gpgsign false

三、创建 Git 仓库测试#

3.1 测试 GPG 签名#

Terminal window
echo "test" | gpg --clearsign
  • 成功弹出 Pinentry 输入密码(或从命令行输入),并生成签名输出,则配置正确
  • 在无 GUI 环境中,可能需要配置 pinentry-ttygpg-agent 才能正常输入口令

3.2 测试 Git commit 签名#

Terminal window
# 创建并初始化项目
mkdir test && cd test
git init
## 配置仓库信息
git config --local user.name user
git config --local user.email user@admin.com
# 启用 gpg 签名
git config --local user.signingkey A385D5291681E2F0FCF5EBA8AC3897D449CE8390
git config --local commit.gpgsign true
# 创建文件并提交
touch test
git add test
git commit -S -m "test commit" # 在已开启 commit.gpgsign 的情况下,-S 参数是可选的,此处显式添加仅用于强调该提交是签名提交

此时输入密钥的密码完成签名操作,使用以下命令查看 Git 提交记录并调用 GPG 验签并打印结果

Terminal window
git log --show-signature -1

示例输出:

commit 1c3059eb547bdaa4f1726a611eec3c4245007269 (HEAD -> master)
gpg: Signature made Tue Sep 3 20:16:27 2025 CST
gpg: using EDDSA key A385D5291681E2F0FCF5EBA8AC3897D449CE8390
gpg: Good signature from "user <user@admin.com>" [ultimate]
Author: user <user@admin.com>
Date: Tue Sep 3 20:16:27 2025 +0800
test commit
NOTE

Git 默认不会对提交进行签名验证
只有在显式指定 --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,也可以在本地确认提交是否真实签名:

Terminal window
git log --show-signature -1

如果本地显示 Good signature,说明签名本身是正确的,问题通常出在 GitHub 侧的邮箱或公钥配置上

使用 GPG 对 Git 提交进行签名
https://www.self4m.com/posts/git-commit-signing-with-gpg/
✍️作者
Self4m
📅发布于
2025-09-15
©️许可协议
CC BY-NC-SA 4.0

商业用途必须事先获得作者授权;
非商业用途可以使用,但必须注明出处;
若有改编需采用相同许可协议发布。