Git 多账号 GPG 签名配置:根据目录自动切换邮箱和签名密钥

背景

很多开发者同时维护多个身份的项目,例如:

身份 邮箱 GPG Key
个人身份 personal@example.com Key A
工作身份 work@example.com Key B

希望达到以下效果:

~/code/personal/*
    ↓
personal@example.com
Key A

~/code/work/*
    ↓
work@example.com
Key B

即:

  • 不同目录下的 Git 仓库自动使用不同邮箱
  • 自动使用对应的 GPG Key 进行 Commit 签名
  • 不需要每个仓库单独配置

Git 提供的 includeIf 功能可以很好地实现这一需求。


第一步:准备 GPG 密钥

查看本机所有 GPG 密钥:

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

示例:

sec   rsa4096/AAAAAAAAAAAAAAAA
uid   Developer One <personal@example.com>

sec   rsa4096/BBBBBBBBBBBBBBBB
uid   Developer One <work@example.com>

记录需要使用的 Key ID:

个人身份:
AAAAAAAAAAAAAAAA

工作身份:
BBBBBBBBBBBBBBBB

第二步:配置默认身份

编辑全局配置文件:

vim ~/.gitconfig

内容如下:

[user]
    name = Developer One
    email = personal@example.com
    signingkey = AAAAAAAAAAAAAAAA

[commit]
    gpgsign = true

[gpg]
    format = openpgp

[includeIf "gitdir:/Users/username/code/work/"]
    path = ~/.gitconfig-work

说明:

  • 默认情况下使用 personal@example.com
  • 默认使用 Key A
  • 当仓库位于 /Users/username/code/work/ 目录下时,额外加载 ~/.gitconfig-work

第三步:创建工作身份配置

创建配置文件:

touch ~/.gitconfig-work

编辑:

vim ~/.gitconfig-work

内容:

[user]
    name = Developer One
    email = work@example.com
    signingkey = BBBBBBBBBBBBBBBB

[commit]
    gpgsign = true

注意:

这里不需要再配置路径。

路径匹配规则已经写在:

~/.gitconfig

中的 includeIf 配置里。


第四步:理解 includeIf 工作原理

假设目录结构如下:

/Users/username/code/

├── personal
│   ├── blog
│   └── dotfiles
│
└── work
    ├── backend
    ├── frontend
    └── service-a

配置:

[includeIf "gitdir:/Users/username/code/work/"]
    path = ~/.gitconfig-work

表示:

只要 Git 仓库位于

/Users/username/code/work/

目录下

自动加载:

~/.gitconfig-work

因此:

/Users/username/code/work/backend

使用:

work@example.com
BBBBBBBBBBBBBBBB

而:

/Users/username/code/personal/blog

使用:

personal@example.com
AAAAAAAAAAAAAAAA

第五步:验证配置是否生效

进入工作项目:

cd ~/code/work/backend

查看邮箱:

git config user.email

输出:

work@example.com

查看签名 Key:

git config user.signingkey

输出:

BBBBBBBBBBBBBBBB

进入个人项目:

cd ~/code/personal/blog

查看邮箱:

git config user.email

输出:

personal@example.com

查看签名 Key:

git config user.signingkey

输出:

AAAAAAAAAAAAAAAA

第六步:查看 Git 实际加载的配置

排查问题时最有用的命令:

git config --list --show-origin

示例:

file:/Users/username/.gitconfig
user.email=personal@example.com

file:/Users/username/.gitconfig-work
user.email=work@example.com

说明:

Git 先加载 ~/.gitconfig

因为目录匹配

再加载 ~/.gitconfig-work

后加载的配置会覆盖前面的配置

第七步:测试 GPG 签名

创建测试提交:

git commit -S --allow-empty -m "test gpg"

查看签名:

git log --show-signature -1

示例:

gpg: Good signature from "Developer One <work@example.com>"

说明当前仓库已经使用对应身份完成签名。


常见问题

includeIf 不生效

检查路径是否完全一致:

[includeIf "gitdir:/Users/username/code/work/"]

建议:

  • 使用绝对路径
  • 保留末尾 /
  • 路径大小写保持一致

查看当前仓库最终使用的邮箱

git config user.email

查看当前仓库最终使用的 GPG Key

git config user.signingkey

查看当前 Commit 使用的签名

git log --show-signature -1

扩展:配置多个身份

例如同时维护个人、工作、开源组织项目:

[includeIf "gitdir:/Users/username/code/work/"]
    path = ~/.gitconfig-work

[includeIf "gitdir:/Users/username/code/opensource/"]
    path = ~/.gitconfig-opensource

[includeIf "gitdir:/Users/username/code/client/"]
    path = ~/.gitconfig-client

每个身份分别配置:

~/.gitconfig-work
~/.gitconfig-opensource
~/.gitconfig-client

即可实现根据项目目录自动切换 Git 邮箱和 GPG 签名密钥。


最终目录结构

~/.gitconfig
~/.gitconfig-work
~/.gitconfig-opensource
~/.gitconfig-client

~/code/personal/*
~/code/work/*
~/code/opensource/*
~/code/client/*

对应关系:

默认身份
↓
personal@example.com
Key A

work 目录
↓
work@example.com
Key B

opensource 目录
↓
opensource@example.com
Key C

client 目录
↓
client@example.com
Key D

这样即可实现根据仓库目录自动切换 Git 身份和 GPG 签名密钥。