Git Multi-Account GPG Signing Configuration: Automatically Switch Email and Signing Keys by Directory

Background

Many developers maintain projects under multiple identities, for example:

Identity Email 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.com is used.
  • Key A is used by default.
  • When a repository resides under /Users/username/code/work/, ~/.gitconfig-work is 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 includeIf directive 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.