Back to Blog

Are You Still Managing GPG Keys When You Could Be Signing Commits with SSH?

Are You Still Managing GPG Keys When You Could Be Signing Commits with SSH?

Are You Still Managing GPG Keys When You Could Be Signing Commits with SSH?

I realized the other day that I’ve spent more time over the last three years troubleshooting my GPG agent than I have actually using GPG for anything other than Git. It’s one of those tools that feels like a vestigial organ—we keep it around because we’re told it’s the "correct" way to get that little green "Verified" badge on GitHub, but it’s often a clunky, opaque mess to manage.

If you’re already using an SSH key to push code to your remote, you're carrying around a perfectly good identity tool. Since Git 2.34, you can stop pretending to understand GPG trust levels and just use SSH to sign your commits.

The "Why" is mostly about sanity

GPG is powerful, but it's a lot of overhead if you just want to prove that you were the one who wrote the code. You have to deal with key expiration, the gpg-agent hanging, and the inevitable headache when you migrate to a new machine and realize you didn't back up your secret subkeys correctly.

SSH keys are different. You already have one. You probably already know how to move it or regenerate it. By switching to SSH signing, you consolidate your identity into a single file pair that you’re already using every day.

Checking your version

Before you try this, make sure your Git version is up to date. You need Git 2.34 or later.

git --version

If you’re on an old version of macOS or a "stable" Linux distro, you might need to update. If you're on something ancient, this won't work, and you're stuck with GPG (or just not signing, which is also a choice).

Setting it up

The transition is surprisingly minimal. You’re essentially telling Git: "Stop looking for gpg and start using the SSH agent for signatures."

1. Tell Git to use the SSH format

First, change the signing format from the default (OpenPGP) to SSH.

git config --global gpg.format ssh

2. Point to your SSH key

You need to tell Git which key to use. This is usually your public key. I prefer pointing to the file path rather than pasting the string, as it’s easier to manage if you rotate keys.

git config --global user.signingkey ~/.ssh/id_ed25519.pub

*Note: If you’re still using RSA keys, change the path accordingly. But really, you should probably be using Ed25519 by now.*

3. Enable signing by default

You can sign individual commits with the -S flag, but that’s a chore. Just turn it on globally so every commit you make is signed automatically.

git config --global commit.gpgsign true

Making the platforms happy

GitHub, GitLab, and Bitbucket all support SSH commit verification now, but they don't necessarily "know" about your signing key just because you use it for authentication.

1. Go to your GitHub Settings > SSH and GPG keys.
2. Click New SSH Key.
3. Under Key type, select Signing Key (this is the crucial step).
4. Paste in your public key (the contents of ~.ssh/id_ed25519.pub).

If you skip the "Key type" selection and just add it as an Authentication Key, GitHub will still let you push code, but your commits will show up as "Unverified."

The "Allowed Signers" Gotcha

Everything above works great for getting that badge on a remote server. But if you want to verify signatures locally—say, to check a colleague's work or your own history via git log --show-signature—Git needs a way to map SSH keys back to users.

You’ll need to create an "allowed signers" file. This is basically a list that says "this email belongs to this key."

Create a file at ~/.ssh/allowed_signers and add a line like this:

[email protected] ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...

Then tell Git to use that file for verification:

git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers

A quick word on security

Purists will argue that GPG is "more secure" because it supports webs of trust and sophisticated key revocation. They aren't wrong, technically. But for the 99% of us working in standard dev environments, the most secure tool is the one you actually use correctly.

If GPG's complexity means you stop signing commits because your agent crashed again, you're less secure than the person with a simple, functional SSH setup.

Troubleshooting

If you get an error like error: gpg failed to sign the data, it’s almost always because your user.signingkey path is wrong or your SSH agent isn't running.

If you're on macOS and using a key with a passphrase, you might need to add this to your ~/.ssh/config to ensure the passphrase is pulled from the Keychain:

Host *
  AddKeysToAgent yes
  UseKeychain yes

That's it. No more GPG agents, no more "secret key not found" errors. Just your SSH key doing double duty.