资讯动态

用SSH Key给Git提交加上Verified签名,告别GPG繁琐配置

发布时间:2026/9/26 22:51:42 来源:尧图企业网站定制
上周我打开 GitHub 的提交记录发现自己刚推上去的 commit 旁边干干净净而同事的提交都带着一个绿色 Verified 小徽章。那感觉就像全班都发了校徽只有你忘戴了。虽然不影响任何功能但我实在忍不了当天花十分钟把这事解决了。用的方案不是大多数教程里推荐的 GPG而是很多人电脑里早就躺着的那把 SSH Key。这篇文章就讲清楚一件事怎么用现成的 SSH Key 给 commit 加上 Verified 标识。它比 GPG 轻量得多不需要额外装软件、不需要维护吊销证书、不需要记住一堆命令。适合这三类人手上已经有 SSH Key、平时主要用 GitHub 或 GitLab 的开发者被 GPG 配置折磨过、最后放弃签名的人以及单纯好奇这个 Verified 到底是怎么来的、想自己独立复现的人。1. 先从为什么开始SSH 签名凭什么是 GPG 的轻量替代品1.1 被 GPG 配置折磨过的开发者都懂Git 的签名机制最早是完全围绕 GPG 设计的。你需要在系统里安装 gpg 工具生成一对专门的密钥设置吊销证书把公钥上传到 keyserver还要对付那个时不时弹出来要密码的 pinentry 窗口。在 Windows 上这套流程更痛苦GPG4Win 装完之后还会出现明明正确输出了公钥、但 GitHub 就是识别不了的情况。更麻烦的是密钥维护。GPG 密钥有有效期到期了你得记得续期吊销证书要是丢了密钥出问题都没法优雅地撤销。这些管理成本对个人开发者来说太重了。很多人的真实状态是跟着教程配完 GPGcommit 上终于有了 Verified然后一年后再也没碰过那把 GPG 密钥甚至哪天真过期了都不知道。这时就能看到 SSH Key 的优势你每天都在用它 push 代码它就是你开发环境里最现成的身份凭证。既然平台本来就存着你的 SSH 公钥用于登录认证让它顺手验证签名几乎零额外成本。1.2 SSH 签名到底是怎么工作的简单说SSH 密钥对除了能做“认证”还天生支持“签名”。所谓签名就是用你的私钥对一段内容生成一个不可伪造的校验信息任何人拿到你的公钥都能验证这段信息确实出自你手。Git 做的事情是在你执行 commit 时把即将提交的内容摘要交给ssh-keygen -Y sign让本地 SSH 私钥对它签名然后把签名结果作为一段特殊信息写进 commit 对象里。等你 push 到 GitHub平台会取出这段签名拿你账号里存的 SSH 公钥去验证。验证通过界面上就显示 Verified验证失败或没有签名就没有徽章。打个比方这有点像快递柜取件取件码若是用你的指纹设备发送给柜机柜机后台备案了你的指纹信息核实无误后才开门。SSH 签名就是那个“指纹”而你的 SSH 公钥就是后台备案的样本。1.3 两条路线的直接对比维度GPG 签名SSH 签名前置条件安装 gpg 工具生成独立密钥对设置吊销证书Git 2.34 以上有一把能登录远端的 SSH Key密钥管理有过期时间吊销证书必须妥善保存普通 SSH Key 无强制过期可随时轮换公钥分发需要导出公钥、上传 keyserver 或手动提供给平台平台本来就必须存你的公钥用于 push 认证客户端依赖需要完整的 GPG 环境Windows 上尤其麻烦依赖系统自带的 ssh-keygen跨平台一致操作直觉日常 push 用不到这把密钥还要单独备份就是你天天在用的那把密钥平台支持方面GitHub 从 2021 年 10 月起支持 SSH 签名验证GitLab 从 15.7 版本开始支持。主流代码托管平台已经把这套路铺平了剩下的就是配置问题。2. 动手前的检查清单版本、密钥、平台账户2.1 Git 版本必须 2.34 以上SSH 签名是 Git 2.34 版本才加入的功能核心体现在gpg.format支持ssh这个取值。如果你的 Git 版本低于 2.34后面的配置全部白搭commit 时甚至会直接报错。所以第一步永远是确认版本git --version如果版本偏低升级方法按系统来Ubuntu/Debiansudo apt update sudo apt install git。注意老发行版自带的 Git 可能仍然很旧必要时加ppa:git-core/ppa这类官方维护源。macOSbrew upgrade git。Windows直接去官网下载最新版安装包Git for Windows 已经内置了适配好的 ssh.exe体验很顺。2.2 检查现成的 SSH 密钥并确认能登录打开终端看~/.ssh目录ls -l ~/.ssh/你会看到类似id_ed25519、id_ed25519.pub或id_rsa、id_rsa.pub的文件。.pub结尾的是公钥没有后缀的是私钥。我的建议是优先使用 ed25519 类型的密钥它比 RSA 短、生成快、安全性也够如果你手头只有 RSA也不是不行但平台方通常要求 RSA 公钥至少 2048 位以上。确认密钥能正常登录远端这一步很关键它能告诉你的密钥确实已经挂到了账号下ssh -T gitgithub.com看到Hi username! Youve successfully authenticated之类的提示说明密钥有效。如果你使用 GitLab把地址换成gitgitlab.com即可。2.3 没有密钥三分钟生成一个如果你发现自己从来没有生成过 SSH Key或者系统提示找不到密钥文件那就现场生成一把ssh-keygen -t ed25519 -C youexample.com -f ~/.ssh/id_ed25519其中-C只是加个备注方便你认出这把密钥是谁的-f指定保存路径一路回车即可。生成完把公钥打印出来cat ~/.ssh/id_ed25519.pub复制这段以ssh-ed25519开头的完整内容下一步会用到。需要注意的是私钥文件没有后缀的那个绝对不能泄露也别往代码仓库里提交。3. 四行命令完成本地配置3.1 核心配置签名格式、密钥路径、自动签名本地配置只需要三行命令逻辑非常直白git config --global gpg.format ssh git config --global user.signingkey ~/.ssh/id_ed25519 git config --global commit.gpgsign true逐条解释一下为什么是这三条gpg.format ssh告诉 Git 使用 SSH 签名格式而不是默认的 OpenPGP。没有这一行Git 不会理你的 SSH Key。user.signingkey指定签名用的私钥文件路径。注意这里填的是私钥不是那个.pub公钥文件。如果你的路径不在默认位置或者你有多个密钥这里务必写绝对路径比如/home/you/.ssh/id_ed25519。commit.gpgsign true让每次 commit 都自动签名不用记着额外加-S参数。这行最容易被漏掉漏掉之后 commit 虽然是新的但完全没有签名信息。配置完成后你可以看一眼最终结果git config --global --list | grep -E gpg|sign正常情况下能看到gpg.formatssh、user.signingkey...、commit.gpgsigntrue三行。看到就说明本地配置已经生效。3.2 临时跳过和强制签名的用法自动签名打开之后绝大多数场景不需要再手动干预。但有两个命令值得知道git commit --no-gpgsign某一次提交临时跳过签名。偶尔有特殊情况比如临时环境里没有私钥。git commit -S即使没开自动签名也可以手动给这一次提交强制签名。另外很多人关心git commit --amend会不会影响签名。只要commit.gpgsign true保持开着amend 生成的新 commit 会自动重新签名所以修改提交信息之后再 push徽章依然是 Verified。真正会出问题的是 amend 时加了--no-gpgsign新提交就没有签名了这点后面排查章节会再提。3.3 如果想让 Tag 也带上签名commit 之外Git 的 tag 也支持同样的签名机制。顺手打开 tag 签名可以在发布版本时获得同样的可信度git config --global tag.gpgsign true加了这行之后打 annotated tag 时同样会用 SSH Key 签名。GitHub 页面上对应 tag 也会显示 Verified。这一步不是必须的但既然 SSH 签名成本这么低顺手开掉不亏。3.4 本地先验证一遍能不能看到 Good git signature配置完成之后建议不要急着 push先在本地验证签名链路是通的。随便开一个仓库做一个新 commit然后查看签名信息git log --show-signature --oneline -3输出里如果能看到Good git signature for ...说明 SSH 签名在本地已经成功。如果你看到error: gpg.ssh.allowedSignersFile一类提示别慌这是本地库缺少公钥信任配置导致的不影响 Git 本身生成签名我们下一节讲平台验证时会说明。4. 把公钥挂到平台上让远端认账4.1 GitHub 的配置路径与邮箱匹配本地签名生成之后远端怎么知道这把签名是你签的答案是把公钥提前存到你的平台账号里。GitHub 的操作路径Settings-SSH and GPG keys-New SSH key把第一步复制的id_ed25519.pub内容粘贴进去。Key type 那一栏选Authentication Key或Signing Key都可以因为 GitHub 对同一把 SSH 公钥是同时支持认证和签名验证的不需要分开建。如果你一把公钥已经在用来 push直接选 Authentication Key它同样能验证签名。有一个细节必须注意GitHub 验证签名时除了公钥要匹配账号提交者邮箱也必须是你账号内关联的邮箱。GitHub 会在账号设置里查你这个 commit 的user.email是否属于该账号。很多人配置完发现还是没有徽章八成就是卡在这里。推荐直接用 GitHub 生成的 noreply 邮箱作为user.email这样既能保护真实邮箱又能稳定匹配账号。4.2 GitLab 的双重用途与注意事项GitLab 的操作在User Settings-SSH Keys。粘贴公钥后在 Usage type 里选择Authentication Signing或者干脆新增一把专门用于签名的密钥把类型设成Signing也行。这里有个需要留意的点GitLab 对 SSH 签名的支持从 15.7 才起步。如果你用的是公司自建的 GitLab先确认版本太老的话界面里根本不会有签名相关选项。GitHub 则没有这个版本包袱网页端早已全面支持。4.3 推送之后亲眼看到 Verified本地签名生成、公钥也挂好接下来 push 到远端等待几秒刷新页面git push origin main打开仓库的 Commits 页面你的 commit 右侧会出现绿色 Verified 标识把鼠标悬停上去会显示类似“This commit was signed with a verified signature”的提示。到这一步整个流程就算完全跑通了。之后每次 commit 是自动签名的所以你只需要正常git commit、正常git push后面每一个新提交都会自动带上这个徽章不需要再做任何额外操作。这也是我喜欢 SSH 签名的一个原因——配置一次之后完全无感。4.4 一个手动校验的小技巧想要在不依赖平台网页的情况下确认某个 commit 的签名有效可以在本地配合公钥做一次手动验证。方法是用 SSH 的allowed_signers机制git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers然后在该文件里按格式写入平台用户的公钥映射格式是“邮箱 域名 密钥类型 base64 公钥”例如youexample.com github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...之后git log --show-signature就能只靠本地文件验证签名而不需要联网询问平台。日常个人使用不必非要配置这个但如果你需要审计代码签名或者团队里要做自动化校验这个机制非常有用。5. 配置过程中绕不开的坑与排查思路5.1 老版本 Git 报错gpg.format ssh 不认账配置完gpg.format ssh后如果 commit 时报类似error: gpg failed to sign the data或者直接提示不支持的签名格式优先怀疑 Git 版本。把git --version的输出对一下低于 2.34 就升级。这里有个隐性坑Linux 发行版很多自带 Git 版本很老比如 Ubuntu 20.04 默认源里 Git 版本只有 2.25根本不支持 SSH 签名。你即使配置了也会在 commit 时莫名其妙失败。升级完版本后记得重新执行一遍第三节的三行配置然后再次确认git config --global --list里的输出。5.2 多密钥环境下签名用错了私钥很多开发者电脑上不止一把 SSH Key。比如公司 GitLab 一把、个人 GitHub 一把通过~/.ssh/config里的 Host 配置区分。这种场景下如果user.signingkey没有显式指定具体私钥路径Git 可能拿默认的那把去签名平台验出来不匹配Verified 就不会出现。排查方法很简单先看git config --global user.signingkey的值对不对再确认 push 用的远端用户名是否与这把密钥匹配。如果存在多账号建议用条件配置来区分例如git config --global includeIf.gitdir:/path/to/work/.git path/path/to/work/.gitconfig然后在你个人的.gitconfig里单独设置对应的user.signingkey、user.name、user.email。这样不同目录下的仓库自动用不同的签名身份互不干扰。5.3 邮箱不匹配导致徽章不显示这是最多人踩的坑。签名本身完全正常本地git log --show-signature显示Good git signaturepush 上去却没有 Verified或者显示 Unverified。原因几乎总是提交邮箱跟平台账号不匹配。你可以在任意一个仓库里查一下当前提交邮箱git config --local user.email然后去 GitHub 的Settings-Emails页面看看这个邮箱是否在列表里。如果不在二选一要么把user.email改成账号内已有的邮箱要么把当前邮箱添加到账号里。GitHub 提供的usernameusers.noreply.github.com格式邮箱通常是最省事的选择——它是隐藏真实邮箱的产物又天然和账号绑定。5.4 commit --amend、rebase 对签名的影响很多人以为 commit 被 amend 过之后原来的签名就永久丢失了。实际不是。当commit.gpgsign true开着amend 和 rebase 都会在生成新 commit 对象时重新签名所以流程结束后签名依然完好。会出问题的场景是执行git commit --amend --no-gpgsign或者某个自动化脚本里手贱关闭了签名导致新提交没有签名。另外如果你 amend 时改了user.email和user.name签名身份会变化平台校验时可能就匹配不上账号了。所以 amend 之后记得跑一遍git log --show-signature -1确认仍然是Good git signature再 push 也不迟。5.5 公司自建 GitLab版本和可见性自建 GitLab 的团队要额外注意版本。GitLab 15.7 之前的版本不支持 SSH 签名验证即便本地配置正确、commit 也带了签名平台上也不会显示任何徽章。这时候要么说服管理员升级 GitLab要么退回 GPG 方案。另外有些自建平台的 SSH Key 管理界面会区分Authentication和Signing用途添加密钥时务必确认类型为 Signing 或 Authentication Signing。很多同事在这卡住是因为他们添加密钥时只勾了 Authentication签名自然验不过。5.6 排查的整体思路不管遇到什么情况按这个顺序排查基本 5 分钟能定位本地git log --show-signature是否显示 Good。如果是问题出在远端如果签名本身失败回到版本和配置检查。检查公钥是否在平台账号中。去 SSH keys 页面看有没有那把.pub的内容。检查提交邮箱与平台账号是否匹配。这是最容易忽略的。检查平台版本与密钥用途类型。按这个顺序走下来90% 的问题都能落在这四个环节里。6. 最后分享几条实践心得SSH Key 给 commit 签名这件事我用了大半年给团队推广也推广了好几轮。最大的体会是这方案的门槛低到可以全员开启。新成员入职只需要确认一把 SSH Key然后两行配置就能保证所有提交全部带签名。比之前用 GPG 时让每个人去生成密钥、保存吊销证书、上传公钥的流程省了太多事。有个小习惯我一直保持每次准备 push 前习惯性跑一下git log --show-signature -1看到 Good 再推。虽然自动签名几乎不会出意外但在团队协作时看到输出里那个 Good 会让人觉得安心。也曾经因为改过邮箱设置commit 推上去显示 Unverified推进去之后才在网页端发现只好用git commit --amend修正后再 push虽然也简单但不如推送前多看一眼省事。如果你之前已经用 GPG 给历史提交签过名也没必要推翻重来。SSH 签名只影响新生成的 commit旧历史保持原样即可。真正从零开始配签名的人直接用 SSH Key 这条路就好没必要再绕到 GPG 那边去。最后再提醒一句所有签名都依赖私钥的保密性。~/.ssh目录的权限、私钥文件的密码保护这些平时就该养成习惯。签名机制只是证明“这把私钥拥有者的身份”如果私钥泄露了任何签名保护都形同虚设。把这套流程配好之后剩下的事情就交给 Git 自动完成你会慢慢喜欢上每次提交都带着 Verified 的踏实感。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑