Verifying Git Commits

Git
GitHub
Author
Affiliation

Tom Jemmett

Published

September 18, 2025

Ever looked at a list of commits on GitHub and noticed ✅ green checks next to some commits, but not others?
Wondered what they mean?

Screenshot of the nhp_inputs repository, showing some verified commits and other unverified commits.

Here’s a screenshot of our nhp_inputs repository.
You can see that some commits (merge commits, specifically here) have those checks, while others don’t.

The green check indicates that the commit has been cryptographically signed — proving it was created by the stated author and hasn’t been tampered with.

There’s nothing stopping someone from changing their Git username and email to impersonate another author.
You might have seen this yourself when your local Git config isn’t set correctly (example and fix).

So, why are those merge commits verified?

When you make a commit directly on GitHub (either by editing a file in the browser or merging a pull request), GitHub knows it’s you and “signs” the commit using its GPG private key.
Others can then independently verify the commit by validating it against GitHub’s public key.

Can you sign your own commits?

Absolutely — and you probably should!
This isn’t just a GitHub feature; it’s built directly into Git.

Below is a screenshot of our nhp_model, where all the commits I’ve authored have been signed with my GPG key.

Screenshot of the nhp_model repository, showing all commits are verified.

Setting up GPG can be a bit of a faff, but there’s an easier way: using SSH keys to sign commits.
You may already have SSH set up for pushing and pulling from GitHub, so this is a no-brainer.
Even if you don’t, setting up SSH is quick.

Easy approach: using SSH

For more details, see “Sign commits with SSH keys” from GitLab’s docs, but here’s the short version:

First, generate an SSH key if you haven’t already. Open a terminal (on Windows you might need Git Bash) and run:

ssh-keygen -t ed25519 -C "my.email@example.com"

This creates a new file called ~/.ssh/id_25519.pub, where ~ is your home directory (for example, on Windows: C:\Users\thomas.jemmett\.ssh\id_25519.pub).

Then run:

git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_25519.pub
git config --global tag.gpgsign true
git config --global commit.gpgsign true

From now on, your commits will be signed — but GitHub won’t yet recognise the signature! You need to upload your SSH key for signing: see“Adding a new SSH key to your account”, GitHub Docs.

You need to make sure that you set this as a key for signing, not for authentication. If you already have uploaded your key for authentication, you need to upload it again for signing. Using the same key for both is fine.

Harder approach: GPG

While GitHub supports SSH-signed commits, not all providers do. GPG is a more established way of performing these cryptographic operations.

It does take more setup, and you may need to install additional tools. Rather than going step by step here, you should read GitHub’s docs on creating a key.

If you do create a GPG key, consider using a modern algorithm like ECDSA or EdDSA.

It’s also a good idea to send your new key to a few keyservers (e.g. pgp.mit.edu, keyserver.ubuntu.com, keys.openpgp.org).

If some of your colleagues also use GPG, you might sign their keys to help establish a Chain of trust.

Paranoid approach

Once your commits are verifiable, you need to ensure your private key never leaks. If an attacker obtained your SSH or GPG key, they could create commits pretending to be you and sign them so others would completely trust them.

If you’re ultra-paranoid (or a maintainer of a popular repository), consider this:

Generate a GPG master key on an air-gapped machine (i.e. not connected to the internet), use it to generate short-lived subkeys, then copy the subkeys to a hardware security key (HSK) like a Yubikey.

If you want a good guide to follow, you might want to read this series of blog posts: (though, I would choose ECC over RSA as suggested). Part 6 explains how to get this to work with a Yubikey.

A good guide is the blog series Applying GPG and Yubikey (I’d recommend ECC over RSA as suggested). Part 6 covers integrating this with a YubiKey.

This approach stores your cryptographic secrets in a way they can’t be extracted (HSKs only import keys, not export them), meaning an attacker would have to physically steal your device.