GPG Keys & Signed Commits: A Practical Guide for GitHub
What GPG keys are, how to create one, and how to wire it up so your GitHub commits show the green "Verified" badge — step by step, no legacy commands.
GitHub can display a green Verified badge on every commit you push — proof that the commit came from you and wasn't tampered with. This guide takes you from zero to signed commits using GPG, the most common signing method for individual developers.
What Is Commit Signature Verification
When you push a commit to GitHub, anyone can claim to be anyone — the author field in a commit is just a string. GPG signing fixes this by attaching a cryptographic signature to each commit using a private key only you hold. GitHub verifies the signature against the public key registered to your account and marks the commit accordingly.
| Status | What it means |
|---|---|
| Verified | Commit is signed and the signature checks out against a key on your account |
| Unverified | Commit is signed but the signature could not be verified |
| (no badge) | Commit is not signed |
Once a commit is verified on GitHub, that verified state is permanent — even if you later revoke or rotate your key, the original verification record stays.
Install GPG
GPG does not ship with macOS or Windows by default.
macOS
brew install gnupgWindows — download the installer from gnupg.org/download. The Gpg4win package includes everything you need.
Linux — GPG is usually pre-installed. If not:
sudo apt install gnupg # Debian/Ubuntu
sudo dnf install gnupg2 # FedoraConfirm the installation:
gpg --versionCheck for Existing GPG Keys
Before generating a new key, see if you already have one:
gpg --list-secret-keys --keyid-format=longIf the output is empty, you have no keys — skip to the next section. If you see output like this, you already have a key pair:
/Users/you/.gnupg/pubring.kbx
------------------------------
sec 4096R/3AA5C34371567BD2 2024-01-15
uid [ultimate] Your Name <you@example.com>
ssb 4096R/4BB6D45482678BE3 2024-01-15The string after the / on the sec line (3AA5C34371567BD2) is your key ID. Jump to Add Your Key to GitHub if you want to use this key.
Generate a New GPG Key
gpg --full-generate-keyWork through the prompts:
| Prompt | What to choose |
|---|---|
| Key type | 1 — RSA and RSA (default) |
| Key size | 4096 |
| Expiration | 0 — does not expire (or set a date if your org requires it) |
| Real name | Your name as it appears on GitHub |
| Your verified GitHub email — or your GitHub no-reply address | |
| Passphrase | Pick a strong one and store it in your password manager |
After confirming, GPG generates the key pair. List your keys to grab the key ID:
gpg --list-secret-keys --keyid-format=longsec 4096R/3AA5C34371567BD2 2026-05-24
uid [ultimate] Deepak Negi <deepak@example.com>
ssb 4096R/4BB6D45482678BE3 2026-05-24Your key ID is 3AA5C34371567BD2 — the part after the / on the sec line.
Export the Public Key
GitHub needs your public key to verify signatures. Export it:
gpg --armor --export 3AA5C34371567BD2This prints a block that starts with -----BEGIN PGP PUBLIC KEY BLOCK-----. Copy the entire block including those header and footer lines.
Add Your Key to GitHub
- Go to GitHub → Settings → SSH and GPG keys
- Click New GPG key
- Give it a descriptive title (e.g.,
MacBook Pro 2026) - Paste the public key block into the Key field
- Click Add GPG key
GitHub will now be able to verify commits signed with the corresponding private key.
Configure Git to Use Your Key
Tell Git which key to use and turn on automatic signing:
# Set your signing key (replace with your actual key ID)
git config --global user.signingkey 3AA5C34371567BD2
# Auto-sign every commit and tag
git config --global commit.gpgsign true
git config --global tag.gpgSign trueIf you previously configured Git to use a different signing format, reset it first:
git config --global --unset gpg.formatThis ensures Git uses the default openpgp format for GPG.
Sign a Commit
With commit.gpgsign true set globally, signing is automatic — just commit normally:
git commit -m "add login page"To sign a one-off commit without the global setting:
git commit -S -m "add login page"Push and open the commit on GitHub — it should display the Verified badge.
Sign a Tag
git tag -s v1.0.0 -m "release v1.0.0"To verify a tag locally before pushing:
git tag -v v1.0.0Verify a Signature Locally
To check a commit's signature without opening GitHub:
git log --show-signature -1A valid signature looks like:
gpg: Signature made Mon 24 May 2026
gpg: using RSA key 3AA5C34371567BD2
gpg: Good signature from "Deepak Negi <deepak@example.com>"Caching Your Passphrase
If Git prompts for your GPG passphrase on every commit, configure the GPG agent to cache it:
# ~/.gnupg/gpg-agent.conf
default-cache-ttl 28800
max-cache-ttl 86400This caches the passphrase for 8 hours (28800 seconds) and up to 24 hours maximum. Reload the agent after editing:
gpgconf --kill gpg-agentThe agent restarts automatically on the next GPG operation.
Quick Checklist
- Install GPG via Homebrew (macOS), Gpg4win (Windows), or your package manager
- Run
gpg --full-generate-key— use RSA 4096, your verified GitHub email, a strong passphrase - Export the public key:
gpg --armor --export <KEY_ID> - Add the public key at GitHub → Settings → SSH and GPG keys
- Set
git config --global user.signingkey <KEY_ID> - Enable auto-signing:
git config --global commit.gpgsign true - Push a commit and check for the Verified badge on GitHub
Symptoms of misconfiguration
error: gpg failed to sign the data→ GPG can't find the key matchinguser.emailin Git; verify they match withgpg --list-secret-keys --keyid-format=long- Commit shows Unverified → your public key is not added to GitHub, or it was added after signing — re-push or force-push after adding the key
- Prompted for passphrase on every commit → configure
gpg-agentcache TTL as shown above gpg: signing failed: No secret key→ the key ID inuser.signingkeydoesn't match any key in your keyring; re-rungpg --list-secret-keys --keyid-format=longand update the config- Windows: Git can't find
gpg→ add the Gpg4winbindirectory to yourPATH, or setgit config --global gpg.program "C:/Program Files (x86)/GnuPG/bin/gpg.exe"