GPG Signing Commits and Tags
Git allows you to sign commits and tags with a GPG key, proving that a particular commit was authored by the person who holds the corresponding private key. Without signing, anyone can set git config user.email to any address and create commits that appear to come from you. Signing adds cryptographic proof of authorship, and GitHub/GitLab/Bitbucket display a green "Verified" badge on signed commits when the signing key is registered with the platform.
Generating a GPG Key
Install GnuPG if needed
# macOS brew install gnupg # Ubuntu/Debian sudo apt install gnupg # Check version gpg --version
Generate a new GPG key pair
gpg --full-generate-key
Interactive prompts during key generation
Please select what kind of key you want:
(1) RSA and RSA (default)
(9) ECC (sign and encrypt) *default*
(10) ECC (sign only)
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Please specify how long the key should be valid.
Key is valid for? (0) 0 ← 0 means no expiry
Is this correct? (y/N) y
Real name: Jane Smith
Email address: jane@example.com
Comment:
You selected this USER-ID:
"Jane Smith <jane@example.com>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? OFinding Your Key ID
List secret keys with long key IDs
gpg --list-secret-keys --keyid-format=long
Example output
/Users/jane/.gnupg/pubring.kbx
-------------------------------
sec rsa4096/3AA5C34371567BD2 2023-01-15 [SC]
A9B1234567890ABCDEF0123456789ABC3AA5C343
uid [ultimate] Jane Smith <jane@example.com>
ssb rsa4096/4BB6D45482678CE3 2023-01-15 [E]The key ID is the part after rsa4096/ on the sec line — in this example, 3AA5C34371567BD2. This is what you configure Git to use.
Configuring Git to Use Your Key
Configure your signing key globally
git config --global user.signingkey 3AA5C34371567BD2 # Tell Git where to find the gpg binary if needed git config --global gpg.program gpg
Signing Individual Commits
Sign a commit with -S flag
git commit -S -m "feat: add user authentication module"
Always Sign Commits (Recommended)
Enable automatic signing for all commits
git config --global commit.gpgsign true # Now all commits are signed without needing -S git commit -m "fix: resolve null pointer exception"
Signing Tags
Create a signed tag
# -s creates a signed tag (lowercase s for GPG) git tag -s v1.0.0 -m "Release v1.0.0 — initial stable release" # Signed annotated tag on a specific commit git tag -s v1.0.0 -m "Release v1.0.0" abc1234
Verifying Signatures
Verify a commit's signature
git verify-commit HEAD # Verify a specific commit git verify-commit abc1234def5678
Good signature output
gpg: Signature made Tue Jan 15 14:32:45 2023 EST gpg: using RSA key 3AA5C34371567BD2 gpg: Good signature from "Jane Smith <jane@example.com>" [ultimate]
Verify a tag's signature
git verify-tag v1.0.0
Good tag signature
object 7d3e5f2a1b9c4d6e8f0a2b4c6d8e0f1a3b5c7d9e type commit tag v1.0.0 tagger Jane Smith <jane@example.com> 1673800365 -0500 Release v1.0.0 — initial stable release gpg: Signature made Tue Jan 15 14:32:45 2023 EST gpg: using RSA key 3AA5C34371567BD2 gpg: Good signature from "Jane Smith <jane@example.com>" [ultimate]
Viewing Signatures in git log
Show signatures in git log
git log --show-signature -1
Example log output with signature
commit 7d3e5f2a1b9c4d6e8f0a2b4c6d8e0f1a3b5c7d9e
gpg: Signature made Tue Jan 15 14:32:45 2023 EST
gpg: using RSA key 3AA5C34371567BD2
gpg: Good signature from "Jane Smith <jane@example.com>" [ultimate]
Author: Jane Smith <jane@example.com>
Date: Tue Jan 15 14:32:45 2023
feat: add user authentication moduleAdding Your Public Key to GitHub
Export your public key to paste into GitHub
# Get your public key in ASCII armor format gpg --armor --export 3AA5C34371567BD2
Copy the entire output including
-----BEGIN PGP PUBLIC KEY BLOCK-----and-----END PGP PUBLIC KEY BLOCK-----Go to GitHub → Settings → SSH and GPG keys → New GPG key
Paste your public key and save
GitHub will now show a green Verified badge on commits signed with this key
Your GitHub account email must match the email in the GPG key
Backing Up Your Private Key
Export private key for secure backup
# Export private key (KEEP THIS SECURE!) gpg --export-secret-keys --armor 3AA5C34371567BD2 > private-key-backup.asc # Export public key (safe to share) gpg --export --armor 3AA5C34371567BD2 > public-key.asc # Import on a new machine gpg --import private-key-backup.asc
Configuring GPG Agent (macOS)
On macOS, you need pinentry-mac so that the GPG passphrase prompt appears as a GUI dialog rather than in the terminal — essential when signing from applications like VS Code.
Configure pinentry-mac
brew install pinentry-mac # Add to ~/.gnupg/gpg-agent.conf echo "pinentry-program $(which pinentry-mac)" >> ~/.gnupg/gpg-agent.conf # Restart the agent gpgconf --kill gpg-agent