Signing your Git commits with GPG is the primary mechanism Git provides to cryptographically verify that a commit was authored by the person who claims to have authored it.

Let’s see this in action. Imagine you’ve made some changes and are about to commit. Normally, you’d just run git commit -m "My changes". But to sign it, you’d add the -S flag:

git commit -S -m "My changes"

If everything is set up correctly, Git will prompt you for your GPG passphrase, and if that’s valid, the commit will be created with a GPG signature attached. You can then verify this signature using git log --show-signature.

git log --show-signature -1

The output will look something like this:

commit abcdef1234567890abcdef1234567890abcdef12
gpg: Signature made Tue 01 Jan 2023 10:00:00 AM UTC
gpg:                using RSA key 0123456789ABCDEF
gpg: Good signature from "Alice <alice@example.com>" [ultimate]
Author: Alice <alice@example.com>
Date:   Tue Jan 1 10:00:00 2023 +0000

    My changes

The "Good signature" line is the magic. It tells you that the commit’s content matches the signature, and that the signature was created by the private key corresponding to the public key associated with "Alice alice@example.com".

The problem this solves is the inherent trustworthiness of digital information. In a distributed version control system like Git, anyone can create a commit with any author name and email. Without a verification mechanism, you have no way to know if the commit you’re looking at was actually written by the person whose name is attached to it. GPG signing addresses this by leveraging public-key cryptography. When you sign a commit, you’re essentially saying, "I, the holder of the private key associated with this public key, attest that this commit was made by me."

Internally, when you run git commit -S, Git takes the commit object (which includes the author, committer, timestamp, and the commit message) and hashes it. This hash is then encrypted using your GPG private key. The resulting encrypted hash is the GPG signature, which Git embeds within the commit object itself.

When git log --show-signature is run, Git extracts the signature and the commit hash. It then uses your GPG public key (which it finds by matching the signature’s key ID) to decrypt the signature, revealing the original hash. If the decrypted hash matches the hash of the commit object, the signature is valid.

The primary lever you control is your GPG key pair. You need to generate a public and private key pair. The public key needs to be shared with others (or put on a keyserver) so they can verify your signatures. Your private key must be kept secure and is protected by a passphrase. Git will use your default GPG key unless you explicitly tell it otherwise. You can configure which key Git uses with git config --global user.signingkey <your_key_id>.

You can list your GPG keys with gpg --list-secret-keys --keyid-format=long. The output will show your key ID, which is the long hexadecimal string (e.g., 0123456789ABCDEF).

The most surprising thing about Git commit signing is how it interacts with SSH keys on many systems. If you have an SSH agent running and have configured Git to use your SSH key for signing (which is a common, though not default, setup), Git might try to use your SSH key instead of your GPG key if you haven’t explicitly configured a GPG signing key. This can lead to confusing errors if your SSH key isn’t properly set up for signing or if you expect GPG to be used. Git’s default behavior is to look for a GPG key, but if user.signingkey is not set and commit.gpgsign is true, it may fall back to SSH if gpg.ssh.use-ssh-keys is also true.

The next hurdle after successfully signing and verifying commits is managing trust in those signatures, which involves GPG’s web of trust model.

Want structured learning?

Take the full Git course →