HomeBlogPublicationsMusicContact

Scoping GPG keys for work and personal git signatures

2025-10-18

Do not leak your work-related signature to your personal (and likely) public github repos

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-agent

On Linux, GPG is usually already available, but if not, you can add it with:

sudo apt install gnupg2 pinentry-tty

You can verify that everything works with:

gpg --version

You 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-key

Choose 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=long

The 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.asc

Store 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.asc

Keep 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.gpgsign

Then open your global ~/.gitconfig and turn it into a dispatcher:

[includeIf "gitdir:~/repos/personal/"]
    path = ~/.gitconfig-personal
 
[includeIf "gitdir:~/repos/work/"]
    path = ~/.gitconfig-work

This 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 = true

Where 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.signingkey

Then move into a work project and ask again:

cd ~/repos/work/dashboard
git config user.email
git config user.signingkey

You’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 -1

You 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> save

If 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 31536000

Then restart the agent:

gpgconf --kill gpg-agent

You 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> save

The 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.