Workflows

签名提交工作流

使用 GPG 或 SSH 签名提交,建立可验证的提交身份和可信协作链。

适合谁看
  • 要把命令组合成稳定流程的团队成员
  • 需要处理协作顺序和分支边界的人
前置知识
  • 知道 fetch / pull / push / branch 的基本作用
  • 能理解一条分支为什么会分叉
常见风险
  • 照抄流程却没确认当前分支关系
  • 在共享分支上用错整合方式

一句话理解

签名提交通过 GPG 或 SSH 密钥对每次提交进行加密签名,让协作者可以验证提交确实来自声称的作者,防止身份伪造和供应链攻击。

签名提交工作流GPG 签名确保提交来源可验证,是开源项目和企业环境中信任链的重要一环。
准备
GPG 密钥对配置 git config公钥上传平台
验证结果
提交带签名标记平台显示 Verified仓库完整性可检
签名不是可选项,而是信任基础设施。从第一天就配置好比中途补救容易。

为什么需要签名提交

在开源项目和大型团队中,任何人都可以设置任意的 user.nameuser.email。恶意攻击者可以伪造身份提交恶意代码。签名提交让身份可验证历史可信任

未签名提交:
commit abc123
Author: Alice <alice@example.com>
  ← 无法证明真的是 Alice

签名提交:
commit def456
Author: Alice <alice@example.com>
gpgsig: -----BEGIN PGP SIGNATURE-----
  ← 可以用 Alice 的公钥验证

GPG 签名工作流

1. 生成 GPG 密钥

# 生成 GPG 密钥(推荐 RSA 4096 或 Ed25519)
gpg --full-generate-key

# 选择密钥类型和大小
# 输入姓名和邮箱(必须与 Git 配置一致)

2. 配置 Git 使用 GPG

# 列出密钥,获取 Key ID
gpg --list-secret-keys --keyid-format=long

# 配置 Git 使用该密钥
git config --global user.signingkey YOUR_KEY_ID

# 默认对所有提交签名
git config --global commit.gpgsign true

# 对标签签名
git config --global tag.gpgsign true

3. 提交并推送

# 如果 commit.gpgsign 未开启,手动签名提交
git commit -S -m "feat: add authentication"

# 创建签名标签
git tag -s v1.0.0 -m "Release version 1.0.0"

# 验证提交签名
git log --show-signature

# 验证标签签名
git tag -v v1.0.0

SSH 签名工作流(Git 2.34+)

相比 GPG,SSH 签名更轻量,可以直接复用你已有的 SSH 密钥。

# 生成 SSH 签名密钥(如果没有)
ssh-keygen -t ed25519 -C "signing@example.com" -f ~/.ssh/git_signing_key

# 配置 Git 使用 SSH 签名
git config --global user.signingkey ~/.ssh/git_signing_key.pub
git config --global gpg.format ssh

# 告诉 Git 哪些公钥是可信的
git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers

# 添加可信签名者
echo "$(git config user.email) $(cat ~/.ssh/git_signing_key.pub)" >> ~/.ssh/allowed_signers

# 签名提交
git commit -S -m "feat: use ssh signing"

平台验证配置

GitHub

# 导出 GPG 公钥
gpg --armor --export YOUR_KEY_ID
# 或导出 SSH 公钥
cat ~/.ssh/git_signing_key.pub

# 复制到 GitHub Settings -> SSH and GPG keys -> New GPG key / Signing Key

GitLab

# 同样导出公钥后添加到 GitLab Profile -> GPG Keys / SSH Keys
# 签名提交后,GitLab 会显示 "Verified" 徽章

团队强制签名策略

通过 GitHub Branch Protection

Settings -> Branches -> Branch protection rules
  -> Require signed commits

通过 Git Hook 校验

# .git/hooks/commit-msg
#!/bin/sh
# 要求所有提交必须签名
git verify-commit HEAD 2>/dev/null || {
  echo "Error: Commit must be signed"
  exit 1
}

混合场景处理

部分提交不签名

# 临时跳过签名
git commit --no-gpg-sign -m "chore: quick fix"

# 只对重要提交签名
git commit -S -m "feat: security-critical change"

多设备使用

# 在不同设备上使用相同的 GPG 密钥
# 导出密钥对
gpg --export-secret-keys --armor YOUR_KEY_ID > private.key

# 在另一台设备导入
gpg --import private.key

# 安全删除导出文件
shred -u private.key

验证失败排查

问题原因解决
gpg failed to signGPG agent 未运行gpgconf --launch gpg-agent
key not foundGit 配置的 key ID 不对检查 user.signingkey
bad signature公钥未上传到平台导出公钥到 GitHub/GitLab
无法验证公钥不在 allowed_signers检查 SSH 签名的 allowedSignersFile

最佳实践总结

  1. 默认开启签名:设置 commit.gpgsign true,让签名成为默认行为
  2. 保护好私钥:GPG/SSH 私钥是身份凭证,使用强密码保护
  3. 设置密钥过期:即使主密钥不过期,子密钥也应设置合理过期时间
  4. 备份密钥:导出并安全备份密钥对,避免丢失后无法验证历史提交
  5. 平台互认:确保公钥已上传到所有使用的 Git 托管平台
  6. 团队统一策略:建议核心分支强制要求签名提交

注意事项

  1. 签名提交会产生额外的元数据,略微增加仓库体积
  2. 初次配置时验证流程可能比较繁琐,但这是一次性投入
  3. 在历史项目中启用签名时,未签名的旧提交不会自动变成已验证
  4. 如果密钥泄露,需要立即撤销并生成新密钥
  5. CI/CD 自动提交通常不需要签名,但关键发布标签建议签名