Signing Commits
Anyone can set user.name and user.email to anything, so the author line of a commit proves nothing on its own. Signing commits with a key you control lets others verify that a commit really came from you — and GitHub shows a Verified badge next to it.
Why it matters
Git records whatever identity is configured. A commit claiming to be from a well-known maintainer could have been made by anyone. Signatures add cryptographic proof: the commit (or tag) is signed with your private key, and anyone with your public key can check it. Some organisations and open-source projects require signed commits on protected branches.
Choosing a key type
| Format | Notes |
|---|---|
| SSH | Simplest — reuse the SSH key you may already have for pushing (lesson 31). Supported since Git 2.34. |
| GPG / OpenPGP | The traditional method; needs GnuPG and its own key management. |
| X.509 (S/MIME) | Certificates issued by an organisation; common in some companies. |
Signing with an SSH key
Tell Git to use SSH signatures and which public key to sign with:
git config --global gpg.format ssh git config --global user.signingkey ~/.ssh/id_ed25519.pub
Sign a single commit with -S, or sign everything automatically:
git config --global commit.gpgSign true git config --global tag.gpgSign true echo "Omelette: eggs, butter" > omelette.txt git add omelette.txt git commit -m "Add omelette recipe"
[main 72fe997] Add omelette recipe 1 file changed, 1 insertion(+) create mode 100644 omelette.txt
(The setting names contain "gpg" for historical reasons; they apply to SSH signing too.)
Verifying signatures
To check SSH signatures locally, Git needs to know which keys belong to whom. That's an allowed signers file: one line per person, with their email and public key.
echo "sam@example.com $(cat ~/.ssh/id_ed25519.pub)" > ~/.ssh/allowed_signers
git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
git log --show-signature -2
commit 72fe997816d883bedac1ad6a1757aecf8eb36c1e (HEAD -> main)
Good "git" signature for sam@example.com with ED25519 key SHA256:BcVhKgf1CLwlPGvEls5r20nskRyXxBFW5IKP+fc93xE
Author: Sam Rivera <sam@example.com>
Date: Mon Mar 2 09:56:00 2026 +0000
Add omelette recipe
commit c4f5e477cc93474bd7d8597fe508a0ba50d132f6
Author: Sam Rivera <sam@example.com>
Date: Mon Mar 2 09:14:00 2026 +0000
Add pancake recipeThe newest commit has a good signature; the older one was made before signing was turned on, so it has none. git verify-commit HEAD and git verify-tag v1.0 check a single commit or tag, and git log --format="%h %G? %s" prints a one-letter status (G good, N none, B bad…):
git log --format="%h %G? %s"
72fe997 G Add omelette recipe c4f5e47 N Add pancake recipe
Showing "Verified" on GitHub
Add the same public key to GitHub as a signing key: Settings → SSH and GPG keys → New SSH key → key type Signing Key. (An SSH key used for both pushing and signing has to be added twice, once as each type.) Your signed commits then show a green Verified badge, as long as the commit email matches a verified email on your account.
GitHub's optional vigilant mode also marks your unsigned commits as "Unverified", making impersonation easy to spot. Commits you make through GitHub's website are signed by GitHub automatically.
GPG in brief
gpg --full-generate-key # create a key gpg --list-secret-keys --keyid-format=long git config --global user.signingkey 3AA5C34371567BD2 git config --global commit.gpgSign true gpg --armor --export 3AA5C34371567BD2 # paste into GitHub → New GPG key
Signed tags
git tag -s v1.0 -m "Release 1.0" creates a signed annotated tag (or plain -a when tag.gpgSign is on). Signing release tags is common even in projects that don't sign every commit, because it lets users verify that a release really came from the maintainers.
Try it yourself
Configure SSH signing with your own key, make a signed commit, and check it with git log --show-signature. Add the key to GitHub as a signing key, push, and look for the Verified badge on the commit page.