Last Updated: 2026-02-06 by Keming He
Important
This guide is for macOS / Linux users with POSIX-compatible shell (sh, bash, zsh).
For Windows users: See GitHub: Managing commit signature verification.
Sign commits with GPG keys for verified badges on GitHub.
- Use Cases - GPG Commit Signing
- Verified badge: Signed commits display a "Verified" badge on GitHub, proving the commit came from you
- Expiration/revocation: Unlike SSH signing, GPG keys can expire or be revoked, giving you more control over key lifecycle
gpg --list-secret-keys --keyid-format=longIf you see keys listed, note the key ID (see Get Key ID for how to read the output). If no keys exist, proceed to generate a new one.
# macOS
brew install gnupg
# Ubuntu/Debian
sudo apt-get install gnupggpg --full-generate-keyWhen prompted:
- Select RSA and RSA (default)
- Key size: 4096 bits
- Expiration: Choose based on your security needs (recommended: 1-3 years)
- Enter your GitHub email address as the user ID
- Set a secure passphrase
Tip
Setting an expiration is good practice - it forces periodic key rotation. When a key expires:
- New signatures fail until you extend or replace the key
- Old signatures remain valid (GitHub still shows "Verified")
- To extend:
gpg --edit-key YOUR_KEY_ID→expire→ set new date →save
After generation, list your keys:
gpg --list-secret-keys --keyid-format=longOutput looks like:
sec rsa4096/ABCDEF1234567890 2026-02-06 [SC] [expires: 2029-02-05]
1234567890123456789012345678901234567890
uid [ultimate] Your Name <your-email@github.com>
ssb rsa4096/FEDCBA0987654321 2026-02-06 [E] [expires: 2029-02-05]Output lines explained:
| Line | Meaning |
|---|---|
sec |
Secret key - your main signing key. rsa4096 = algorithm and key size. [SC] = Sign + Certify capabilities |
| (indented) | Fingerprint - full 40-character hex identifier |
uid |
User ID - your identity (name + email). [ultimate] = you fully trust this key |
ssb |
Secret subkey - typically for encryption. [E] = Encrypt capability |
Key identifier types (for export and signing config):
Tip
Use long ID or fingerprint - never short ID. Long ID is readable and sufficient for personal use. Fingerprint is more explicit - prefer it in shared/organizational contexts.
| Type | Length | Example | Where | Collision risk |
|---|---|---|---|---|
| Short ID | 8 hex | 34567890 |
Last 8 chars of long ID | High - avoid |
| Long ID | 16 hex | ABCDEF1234567890 |
After rsa4096/ on sec line |
Low |
| Fingerprint | 40 hex | 1234567890123456789012345678901234567890 |
Full line below sec |
None |
Use your long ID or fingerprint from Get Key ID:
gpg --armor --export ABCDEF1234567890
# or with fingerprint:
gpg --armor --export 1234567890123456789012345678901234567890Copy the entire output, including -----BEGIN PGP PUBLIC KEY BLOCK----- and -----END PGP PUBLIC KEY BLOCK-----.
- Go to GitHub Settings > SSH and GPG keys
- Click New GPG key
- Title: descriptive name (e.g., "[Device Name] [YYYY]")
- Paste your public key into the Key field
- Click Add GPG key
Note
One GPG key per identity. If you have multiple Git identities (work/personal), see Multiple Identities for directory-based auto-switching.
Use your long ID or fingerprint from Get Key ID:
git config --global user.signingkey ABCDEF1234567890
# or with fingerprint:
git config --global user.signingkey 1234567890123456789012345678901234567890git config --global commit.gpgsign trueAdd to your shell profile (~/.bashrc, ~/.zshrc, etc.):
export GPG_TTY=$(tty)Then reload your shell:
source ~/.zshrc # or ~/.bashrcIf you enabled auto-signing in Configure Git, all commits are signed automatically:
git commit -m "your commit message" # Automatically signedTo manually sign a single commit (if auto-signing is disabled):
git commit -S -m "your commit message"To skip signing for a single commit:
git commit --no-gpg-sign -m "your message"git log --show-signature -1If configured correctly, you'll see signature verification info in the output.
Symptom:
error: gpg failed to sign the data
fatal: failed to write commit objectRunning gpg --list-secret-keys --keyid-format=long hangs or shows waiting for lock.
Solution:
# 1. Kill GPG agent
gpgconf --kill gpg-agent
# 2. Remove lock files
find ~/.gnupg -name "*.lock" -delete
# 3. Verify fix
gpg --list-secret-keys --keyid-format=long # Should respond immediately
echo "test" | gpg --clearsign # Should sign successfully
# 4. Retry your commitPrevention: Lock files occur when GPG processes are interrupted. Run gpgconf --kill gpg-agent periodically to prevent stale processes.
If the issue persists and you need to commit urgently, see Skip Signing.