Git — Signing Commits & Tags
Why Sign?
Signed commits and signed tags provide cryptographic proof that a commit originated from you and has not been tampered with. Hosting services like GitHub and GitLab display a verified badge for signatures they can validate.
Git traditionally uses GPG for signing. Since Git 2.34, you can also use SSH keys, which are often already set up for repository authentication.
Configuration
Tell Git to use SSH format instead of GPG:
# Use SSH keys for signing
git config --global gpg.format ssh
# Point to your public key file
git config --global user.signingkey ~/.ssh/id_ed25519.pub
# Tell Git where to find allowed signers
git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signersThe allowed_signers file maps email addresses to public keys. Create or update it:
echo "$(git config --get user.email) namespaces=\"git\" $(cat ~/.ssh/id_ed25519.pub)" >> ~/.ssh/allowed_signersEach line has three fields separated by spaces:
- Email address — must match
user.emailin Git config - Namespaces —
namespaces="git"restricts the key to Git signing - Public key — the full contents of the
.pubfile
Register the Key on Your Hosting Service
Usage
Sign individual commits or tags:
# Sign a commit
git commit -S -m "Your commit message"
# Sign an annotated tag
git tag -s v1.0 -m "Release 1.0"To sign automatically for every commit and tag:
# Global (all repositories)
git config --global commit.gpgsign true
git config --global tag.gpgsign true
# Per-repository only
git config commit.gpgsign true
git config tag.gpgsign true
# Verify local settings
git config list --local | grep signOther Signatures
Verify other SSH-signed commits by adding the signer to ~/.ssh/allowed_signers:
# Format: email namespaces="git" public_key
echo "their@email.com namespaces=\"git\" ssh-ed25519 AAAAC3..." >> ~/.ssh/allowed_signersFor GPG-signed commits, the process differs: import the signer’s GPG public key into your keyring:
gpg --import path-to-their-key.asc
# or fetch from a keyserver
gpg --keyserver keyserver.ubuntu.com --recv-keys $KEY_IDVerify Signatures
Check whether a commit or tag is signed and valid:
# Show commit with signature verification
git show --show-signature $commit
# Convenience alias
git config --global alias.ss 'show --show-signature'
git ss HEADA bad signature indicates tampering or a missing public key.
Troubleshooting
gpg: no default secret key: No secret key
- Ensure
user.signingkeypoints to a valid public key file (.pub) - Verify the corresponding private key exists and is loadable by your SSH agent
gpg: no valid Trusted Composer or signature not recognized by hosting service
- Confirm the public key is registered on the hosting platform with the correct type
- Verify
user.emailmatches the email associated with the key
Signature shows as unsigned on GitHub/GitLab
- The email in
allowed_signersmust matchuser.emailexactly - The public key in
allowed_signersmust match the one registered on the platform - Re-commit after any configuration changes; signatures are baked into the commit object