Setup GPG signing for your git commits

Have you ever noticed how some git commits on GitHub have Verified beside them? Merge commits for example typically have these. let's get you all set up so every commit you make is automatically signed so GitHub can verify that it was really you who made this commit and show the verified badge next to it.

Create GPG Key

The first thing that we need to do is create a gpg key-pair to sign the commits, you can check if you already have a key on your machine by issuing the following command in a terminal window

gpg --list-secret-keys --keyid-format=long

if you already have a key that you'd like to use, jump to the next step, otherwise, follow along.

the first step to generate a key is to install the gpg tools, I'm on mac so I can install them using

brew install gnupg pinentry-mac

we need the first package to interact with gpg and the second one so we can integrate Apple Keychain with the gpg tool to save the key password in Keychain so we don't have to keep typing the password over and over.

keep in mind that if your email is not verified on GitHub you will not be able to use this feature.

now that we have gpg tools available we can generate a new key, you'll need to answer a few questions to complete the generation, here are my answers (which were the defaults at the time of writing this post)

Key Type: ECC (sign and encrypt)
Curve Type: Curve 25519
Key Expiration: 0 (Does not expire)
Real Name: Yazan Stash
Email Address: This must be the verified email on your GitHub account. You can use your GitHub-provided no-reply email address if you'd like to keep your email address private.
Comment: Leave empty
Password: Choose a strong password for your key

gpg --full-generate-key

if the previous command was successful you should see a message like public and secret key created and signed. along with the key details.

public and secret key created and signed.
 
pub ed25519 2024-08-07 [SC]
YGWWDQD7A9TQHCKDRA7MLVR175REVADWHG4PTQV3
uid Yazan Stash <[email protected]>
sub cv25519 2024-08-07 [E]

Upload your key to GitHub

Alright, now we have a key, we need to let GitHub know about it so that when we sign a commit with our key and push it, they can verify it using our public key. we need to get the ID of the key first so we can export it, let's list all our keys

$ gpg --list-secret-keys --keyid-format=long
---------
sec ed25519/BSM2I6UHWLKDXKKX 2024-08-07 [SC]
YGWWDQD7A9TQHCKDRA7MLVR175REVADWHG4PTQV3
uid [ultimate] Yazan Stash <[email protected]>
ssb cv25519/FTS5KXGI7Z8FTKUX 2024-08-07 [E]

then grab the key ID from the previous command to export it, in my case it's BSM2I6UHWLKDXKKX in this line sec ed25519/BSM2I6UHWLKDXKKX 2024-08-07 [SC] after the slash. Keep this ID around because we'll need it in the next couple of steps. To export the key you can issue

gpg --armor --export BSM2I6UHWLKDXKKX

and copy your GPG key, beginning with -----BEGIN PGP PUBLIC KEY BLOCK----- and ending with -----END PGP PUBLIC KEY BLOCK-----

Finally, we're ready to upload the key to GitHub, you can go to your GitHub keys settings page and beside GPG Keys click New GPG key. Just give it a declarative name and paste it into the key field and click add.

You're done, we just need to tell Git to use this key.

Tell Git about your key

Before we give Git our key, we first need to make sure it doesn't have bad memories from the old times

git config --global --unset gpg.format

now remember the key ID I told you to keep around before? get it and come execute this command. If you don't want Git to use this key for every repo on this machine, omit --global from the command

git config --global user.signingkey BSM2I6UHWLKDXKKX

then I suggest you tell Git to sign all commits by default, otherwise, you'll have to append -S to every commit command. Similar to the command before, if you don't wish this to be the default for all repos, omit --global from the command

git config --global commit.gpgsign true

and the last step is to let gpg use pinentry-mac as the pinentry program to save the key password in Keychain.

echo "pinentry-program $(which pinentry-mac)" >> ~/.gnupg/gpg-agent.conf
killall gpg-agent

That's it!

You're now ready to roll. From now on every commit you make on that repo (or all repos if you choose to) will be signed before being pushed, and then GitHub will verify the signature using the public key we uploaded. Sweet verified badge on all commits 🚀

That's it for now, till the next one, stay curious 🤙🏼