Background
Many developers maintain projects under multiple identities, for example:
| Identity | GPG Key | |
|---|---|---|
| Personal | personal@example.com | Key A |
| Work | work@example.com | Key B |
The desired outcome is as follows:
~/code/personal/*
↓
personal@example.com
Key A
~/code/work/*
↓
work@example.com
Key B
That is:
- Git repositories in different directories automatically use different email addresses.
- Commits are automatically signed with the corresponding GPG key.
- No per-repository configuration is required.
Git’s includeIf feature can accomplish this elegantly.
Step 1: Prepare GPG Keys
List all GPG keys on your machine:
gpg --list-secret-keys --keyid-format LONG
Example output:
sec rsa4096/AAAAAAAAAAAAAAAA
uid Developer One <personal@example.com>
sec rsa4096/BBBBBBBBBBBBBBBB
uid Developer One <work@example.com>
Record the Key IDs you need:
Personal identity:
AAAAAAAAAAAAAAAA
Work identity:
BBBBBBBBBBBBBBBB
Step 2: Configure Default Identity
Edit your global Git configuration file:
vim ~/.gitconfig
Contents:
[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
Explanation:
- By default,
personal@example.comis used. Key Ais used by default.- When a repository resides under
/Users/username/code/work/,~/.gitconfig-workis loaded additionally.
Step 3: Create Work Identity Configuration
Create the configuration file:
touch ~/.gitconfig-work
Edit it:
vim ~/.gitconfig-work
Contents:
[user]
name = Developer One
email = work@example.com
signingkey = BBBBBBBBBBBBBBBB
[commit]
gpgsign = true
Note:
- You do not need to re-specify paths here.
- The path-matching rule is already defined in the
includeIfdirective inside:
~/.gitconfig
Step 4: Understand How includeIf Works
Assume the following directory structure:
/Users/username/code/
├── personal
│ ├── blog
│ └── dotfiles
│
└── work
├── backend
├── frontend
└── service-a
Configuration:
[includeIf "gitdir:/Users/username/code/work/"]
path = ~/.gitconfig-work
Means:
Any Git repository located under
/Users/username/code/work/
will automatically load:
~/.gitconfig-work
Therefore:
/Users/username/code/work/backend
uses:
work@example.com
BBBBBBBBBBBBBBBB
Whereas:
/Users/username/code/personal/blog
uses:
personal@example.com
AAAAAAAAAAAAAAAA
Step 5: Verify That Configuration Is Active
Enter a work project:
cd ~/code/work/backend
Check email:
git config user.email
Output:
work@example.com
Check signing key:
git config user.signingkey
Output:
BBBBBBBBBBBBBBBB
Enter a personal project:
cd ~/code/personal/blog
Check email:
git config user.email
Output:
personal@example.com
Check signing key:
git config user.signingkey
Output:
AAAAAAAAAAAAAAAA
Step 6: View Git’s Actual Loaded Configuration
The most useful command for troubleshooting:
git config --list --show-origin
Example output:
file:/Users/username/.gitconfig
user.email=personal@example.com
file:/Users/username/.gitconfig-work
user.email=work@example.com
Explanation:
Git first loads ~/.gitconfig.
Because the current directory matches the condition,
it then loads ~/.gitconfig-work.
Later-loaded configurations override earlier ones.
Step 7: Test GPG Signing
Make a test commit:
git commit -S --allow-empty -m "test gpg"
View signature:
git log --show-signature -1
Example output:
gpg: Good signature from "Developer One <work@example.com>"
This confirms the current repository has successfully signed using the correct identity.
Common Issues
includeIf Not Taking Effect
Verify that the path matches exactly:
[includeIf "gitdir:/Users/username/code/work/"]
Recommendations:
- Use absolute paths.
- Retain the trailing
/. - Ensure case sensitivity matches exactly.
Check the Final Email Used in Current Repository
git config user.email
Check the Final GPG Key Used in Current Repository
git config user.signingkey
Check Signature of Most Recent Commit
git log --show-signature -1
Extension: Configuring Multiple Identities
For example, maintaining personal, work, and open-source organization projects:
[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
Configure each identity separately:
~/.gitconfig-work
~/.gitconfig-opensource
~/.gitconfig-client
This enables automatic switching of Git email and GPG signing keys based on project directory.
Final Directory Structure
~/.gitconfig
~/.gitconfig-work
~/.gitconfig-opensource
~/.gitconfig-client
~/code/personal/*
~/code/work/*
~/code/opensource/*
~/code/client/*
Correspondence:
Default identity
↓
personal@example.com
Key A
work directory
↓
work@example.com
Key B
opensource directory
↓
opensource@example.com
Key C
client directory
↓
client@example.com
Key D
This achieves automatic switching of Git identity and GPG signing keys based on repository directory.