Git — Signing Commits & Tags

Git
Terminal
Published

July 15, 2026

Modified

July 15, 2026

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_signers

The 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_signers

Each line has three fields separated by spaces:

  1. Email address — must match user.email in Git config
  2. Namespacesnamespaces="git" restricts the key to Git signing
  3. Public key — the full contents of the .pub file

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 sign

Other 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_signers

For 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_ID

Verify 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 HEAD

A bad signature indicates tampering or a missing public key.

Troubleshooting

gpg: no default secret key: No secret key

  • Ensure user.signingkey points 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.email matches the email associated with the key

Signature shows as unsigned on GitHub/GitLab

  • The email in allowed_signers must match user.email exactly
  • The public key in allowed_signers must match the one registered on the platform
  • Re-commit after any configuration changes; signatures are baked into the commit object