GPG Commit Signing Setup¶
This guide covers setting up GPG signing for your Git commits on Bitbucket, GitHub, and other Git hosting providers.
Quick Setup¶
Run the automated setup script:
This script will:
1. Check if GPG is installed (or install via brew install gnupg)
2. List existing GPG keys or help you create a new one
3. Configure your signing key in ~/.config/git/local.gitconfig
4. Display your public key for uploading to your Git provider
Manual Setup¶
1. Install GPG¶
2. Generate a GPG Key¶
Choose: - Key type: RSA (default) - Key size: 4096 bits - Expiration: 0 (key does not expire) or set an expiration date - Enter your name and email (use your work email for work repos) - Set a secure passphrase (recommended)
3. List Your Keys¶
Output will look like:
sec rsa4096/EFF15FEC389D0F89 2026-06-02 [SC]
C1B65DCB44FC8C42E2762273EFF15FEC389D0F89
uid [ultimate] Your Name <your.email@example.com>
The key ID is EFF15FEC389D0F89 (after the / on the sec line).
4. Configure Git¶
Edit ~/.config/git/local.gitconfig:
The main ~/.gitconfig sets gpg.format = openpgp and points Git at your gpg program, but leaves commit.gpgsign = false by default. To sign every commit on this machine, also enable signing in ~/.config/git/local.gitconfig:
To sign only in specific directories instead, leave the global default off and use Per-Organization (Conditional) Signing below — those configs enable signing automatically.
5. Export Your Public Key¶
Copy the entire output (including the -----BEGIN PGP PUBLIC KEY BLOCK----- and -----END PGP PUBLIC KEY BLOCK----- lines).
6. Upload to Your Git Provider¶
Bitbucket¶
- Go to: https://bitbucket.org/account/settings/gpg-keys/
- Click "Add key"
- Paste your public key
- Click "Add key"
GitHub¶
- Go to: https://github.com/settings/keys
- Click "New GPG key"
- Paste your public key
- Click "Add GPG key"
GitLab¶
- Go to: https://gitlab.com/-/profile/gpg_keys
- Paste your public key
- Click "Add key"
Per-Organization (Conditional) Signing¶
The committed gitconfig can select a different identity and signing key automatically based on which directory a repository lives in, using Git's includeIf directives. This is useful when you contribute to multiple organizations that each require a different email and signed commits.
Organize repositories by organization¶
~/Code/
├── work1/ # Organization 1 — auto-signs with org 1 email + key
├── work2/ # Organization 2 — auto-signs with org 2 email + key
└── personal/ # Personal projects
How it works¶
The main gitconfig pulls in an organization-specific config when you work under the matching directory:
[includeIf "gitdir:~/Code/work1/"]
path = ~/.config/git/work1.gitconfig
[includeIf "gitdir:~/Code/work2/"]
path = ~/.config/git/work2.gitconfig
Each organization config overrides user.email and user.signingkey, and sets commit.gpgsign = true, so commits made anywhere under that directory are signed with the right key.
Set up an organization¶
- Generate a key for the organization and upload its public key to that org's Git host (see Manual Setup above).
- Create the organization config from the template (it is never committed):
Repeat for
cp ~/dotfiles/templates/config/git/work.gitconfig.template ~/.config/git/work1.gitconfig # Edit ~/.config/git/work1.gitconfig: set the organization email and signing key IDwork2, etc. The directories matched byincludeIf(~/Code/work1/,~/Code/work2/) are defined ingitconfig— adjust them there if your layout differs.
Verify¶
This checks that repositories under each configured organization directory resolve to the expected email, signing key, and commit.gpgsign = true, reading the per-organization ~/.config/git/*.gitconfig files. It prints a PASS / FAIL line per organization and exits non-zero if any are misconfigured.
Verify Signing¶
Make a test commit:
You should see gpg: Good signature from "Your Name <your.email@example.com>".
Push to Bitbucket and check the commit — it should show a "Verified" badge.
Troubleshooting¶
GPG prompts for passphrase on every commit¶
Install pinentry-mac to cache your passphrase:
brew install pinentry-mac
echo "pinentry-program $(which pinentry-mac)" >> ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agent
"gpg failed to sign the data" error¶
Check your GPG agent:
If this fails, restart the GPG agent:
Commits are not signed at all¶
The committed gitconfig ships with commit.gpgsign = false. Confirm signing is enabled and see which config provides each value:
git config --show-origin --get commit.gpgsign
git config --show-origin --list | grep -E 'user\.(email|signingkey)|commit\.gpgsign'
Enable it globally in ~/.config/git/local.gitconfig ([commit] gpgsign = true), or rely on the per-organization configs described above.
Disable signing globally (emergency rollback)¶
Wrong key being used¶
Make sure ~/.config/git/local.gitconfig has the correct key ID:
Update it if needed:
SSH Signing (Alternative)¶
If you prefer SSH signing instead of GPG:
-
In
~/.gitconfig, change: -
In
~/.config/git/local.gitconfig: -
Create
~/.config/git/allowed_signers:
SSH signing is simpler but may not be supported by all Git providers.