I deal with personal and work related repos on a daily basis, and building on the previous post about separating personal and work credentials, I will now add GPG keys for signed commits.
We’ll build a configuration where Git automatically chooses the right GPG key based on where you are in your filesystem. No toggles, no manual switches, and overall no “sh!t my work GPG is now public in github”.
Why use GPG at all?
GPG is the open-source implementation of the OpenPGP standard — the machinery that underpins encrypted email, secure messaging, and commit signing. It’s an asymmetric cryptographic system: you have a public key that you give freely to others, and a private key that you guard closely.
In Git, GPG serves a simple purpose: it proves authorship. A commit signed with your private key is verifiable by anyone who holds your public key. It becomes a mathematical handshake between you and whoever reads your code later. No amount of impersonation can recreate it.
The structure of your digital workshop
Let’s start with a similar setting that in the previous
post. Imagine you keep your code under a ~/repos directory, with two separate realms:
~/repos/
├── personal/
│ ├── blog/
│ ├── side-project/
│ └── dotfiles/
└── work/
├── project1/
├── project2/
└── project3/Everything inside personal/ will use your private, personal GPG key and email address. Everything under work/ will use your professional credentials. You’ll never have to tell Git which one to use — it will simply know.
Installing the right tools
On macOS, the simplest route is through Homebrew. You can install both GPG itself and a small helper called pinentry-mac, which manages the password prompt that appears when your private key is used:
brew install gnupg pinentry-mac
echo "pinentry-program /opt/homebrew/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agentOn Linux, GPG is usually already available, but if not, you can add it with:
sudo apt install gnupg2 pinentry-ttyYou can verify that everything works with:
gpg --versionYou should see a version number and a list of supported algorithms.
Generating your keys
Creating a GPG key is not unlike drawing up a digital birth certificate. Each key pair carries a name, an email, and an expiration date — the minimal ingredients of identity.
Start with your personal key:
gpg --full-generate-keyChoose elliptic-curve cryptography (ed25519), which is compact and modern. Set an expiry period (one
year is a healthy default; you can renew later). Enter your personal email, such as Name Lastname
<me@personal.com>. When prompted for a passphrase, choose something strong and memorable.
Repeat the process for your work account, this time with your professional address: Name Lastname
<work@company.com>.
Once created, you can inspect your keys:
gpg --list-secret-keys --keyid-format=longThe output will show each identity along with a long hexadecimal identifier. Those key IDs are what Git will later use to know which signature belongs to which world.
Securing your keys
Your GPG keys are more than just files. They are small, portable proofs of who you are — mathematical extensions of your identity. If your private key is ever stolen, someone could impersonate you with perfect fidelity. This makes the protection of your keys not a technical chore, but a matter of self-defence.
When you generate a key, GPG encrypts it inside your ~/.gnupg/ directory using your chosen passphrase. The strength of that passphrase determines how hard it is for anyone to unlock your digital signature. Weak or reused passwords are invitations; strong, unique ones are fortresses.
Because your key represents a one-of-a-kind identity, it must also be backed up with care. If your computer dies and you have no backup, the loss is irreversible — you will never again be able to decrypt messages encrypted to that key, nor can you sign commits to prove they’re yours. To prevent that, export your private keys to an encrypted USB drive or other offline medium. GPG makes this easy:
gpg --armor --export-secret-keys "me@personal.com" > personal_secret_backup.ascStore the resulting file somewhere physically secure — ideally somewhere you would also trust to keep your passport.
A companion to every key is its revocation certificate. Think of it as your emergency brake. If you ever lose access to your private key or suspect it has been stolen, you can publish this certificate to tell the world to stop trusting it:
gpg --gen-revoke "me@personal.com" > personal_revocation.ascKeep this file offline too. It doesn’t reveal any secrets; it merely gives you a way to say this key is no longer mine.
Finally, remember that your public key is meant to travel. Share it widely. Upload it to GitHub or GitLab, send it to collaborators, even publish it on a keyserver. It’s your digital signature card — the piece others use to verify you.
Teaching Git to know where you are
Git itself doesn’t understand identity beyond the configuration files you give it. By default, it uses a single global name, email, and signing key for everything you do. That’s convenient for hobbyists but clumsy for professionals who live in two domains.
We’ll use conditional includes to fix that — a small Git feature that loads different configurations depending on the path you’re working in.
First, clear out any old global settings that might interfere:
git config --global --unset user.name
git config --global --unset user.email
git config --global --unset user.signingkey
git config --global --unset commit.gpgsignThen open your global ~/.gitconfig and turn it into a dispatcher:
[includeIf "gitdir:~/repos/personal/"]
path = ~/.gitconfig-personal
[includeIf "gitdir:~/repos/work/"]
path = ~/.gitconfig-workThis tells Git, “When I’m inside this directory, load that configuration file.”
Now create those two profiles.
~/.gitconfig-personal:
[user]
name = Name Lastname
email = me@personal.com
signingkey = 1234ABCD5678EF90
[commit]
gpgsign = true~/.gitconfig-work:
[user]
name = Name Lastname
email = work@company.com
signingkey = ABCD1234EF905678
[commit]
gpgsign = trueWhere the signingkey value is that hexadecimal value we mentioned some steps above.
That’s it. From now on, Git will silently choose the right identity depending on which folder you’re in. The configuration doesn’t just keep you organised; it enforces discipline without friction.
Testing the setup
Move into a personal repository and ask Git who you are:
cd ~/repos/personal/blog
git config user.email
git config user.signingkeyThen move into a work project and ask again:
cd ~/repos/work/dashboard
git config user.email
git config user.signingkeyYou’ll see the right values in each case. You can now commit normally, and Git will sign with the appropriate key.
To test signing directly:
git commit -S --allow-empty -m "signing check"
git log --show-signature -1You should see a line confirming a “Good signature” from the right address.
You may want to alias git commit -S -m (I do at least).
Publishing your public keys
On GitHub, go to Settings → SSH and GPG keys and add your public key. On GitLab, do the same under User Settings → GPG Keys.
Once your public keys are registered, any signed commits you push will display a neat little Verified badge next to your name — a subtle but reassuring mark of authenticity.
Key maintenance and renewal
Every key deserves a bit of housekeeping. Keys can expire, and that’s a good thing — it forces you to renew them periodically and confirm that you still control them.
When a key is about to expire, extend its validity:
gpg --edit-key "me@personal.com"
gpg> key 1
gpg> expire
gpg> saveIf a key is compromised, use your revocation certificate to invalidate it publicly, then create a new one. GPG’s philosophy is simple: it’s better to assume keys will eventually need renewal than to rely on eternal trust.
Keeping things pleasant
Typing your passphrase for every commit can quickly become tedious. Fortunately, GPG includes an agent that can cache decrypted keys for a configurable period of time. You can adjust it in ~/.gnupg/gpg-agent.conf:
default-cache-ttl 86400
max-cache-ttl 31536000Then restart the agent:
gpgconf --kill gpg-agentYou can also mark your own keys as fully trusted to suppress redundant warnings:
gpg --edit-key "me@personal.com"
gpg> trust
# choose 5 = ultimate
gpg> saveThe reward: clarity and confidence
What you end up with is not just convenience, but composure. You can move between worlds —home and office, personal and professional— without stopping to check your configuration. Every commit you make carries a truthful cryptographic signature that says, “This came from me, in this context.”
You don’t have to worry about global settings, nor about accidental cross-signing. The structure itself enforces correctness.
Your ~/.gnupg directory holds your encrypted private keys, your .gitconfig dispatcher knows where you are, and Git quietly does the right thing. It’s the kind of invisible reliability that makes for good security: something you forget is even there.