How it works
The explanation, with examples you can run.
Sign with an SSH key
In real use you would point at your existing key, such as ~/.ssh/id_ed25519.pub, and set these with --global. Here a throwaway key keeps the example self-contained.
git init -q -b main demo && cd demossh-keygen -q -t ed25519 -N "" -C "ada@example.com" -f ../demo_keygit config gpg.format sshgit config user.signingkey ../demo_key.pubgit config commit.gpgsign trueecho hi > a.txt && git add a.txt && git commit -q -m "Signed change"git cat-file -p HEAD | head -5tree 0d8a474fc67971fb3dd7616e26323d3066442555author Ada <ada@example.com> 1767607200 +0000committer Ada <ada@example.com> 1767607200 +0000gpgsig -----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAg...(The signature lines are shortened here; yours will differ because your key differs.) The signature sits in a gpgsig header inside the commit object, so it is part of the commit's hash. Rebasing or amending creates a new commit without it, so with commit.gpgsign on, Git signs the replacement automatically.
Verify
Git needs to know which keys to trust for which identities. For SSH that is an allowed signers file, one line per person:
echo "ada@example.com $(cat ../demo_key.pub)" > ../allowed_signersgit config gpg.ssh.allowedSignersFile ../allowed_signersgit verify-commit HEADGood "git" signature for ada@example.com with ED25519 key SHA256:...git log --show-signature prints the same check for each commit, and git verify-tag v1.0.0 checks a tag signed with git tag -s. Teams can keep a shared allowed signers file in the repository so everyone verifies against the same list.
On hosting services
GitHub, GitLab and Bitbucket verify signatures against keys uploaded to the user's account. On GitHub you add the SSH key a second time as a signing key (an authentication key is not enough), and signed commits then show a Verified badge. Branch protection rules can require signed commits on main.
What signing does and doesn't do
- It proves a key signed this exact object. If the commit changes in any way, verification fails.
- It doesn't prove the code is good, or that the person is who the email says unless you trust how the key was registered.
- Losing a key matters. Protect the private key with a passphrase or a hardware key (
ssh-keygen -t ed25519-skfor FIDO keys), and remove it from your account if it leaks. - Merges made on the server are signed by the host's key, not yours.
- Sign releases at least. Signing every commit is common in security-sensitive projects; signing release tags is the minimum worth doing, because a tag is what people build and install from.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.