GitGPG Signing Commits

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

Bash
# macOS
brew install gnupg

# Ubuntu/Debian
sudo apt install gnupg

# Check version
gpg --version

Generate a new GPG key pair

Bash
gpg --full-generate-key

Interactive prompts during key generation

Text
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? O
Tip
Use RSA 4096 for maximum compatibility. The newer ECC (ed25519) keys are smaller and faster but may not be supported by all older systems and integrations. For a personal development key, either is fine.
Finding Your Key ID

List secret keys with long key IDs

Bash
gpg --list-secret-keys --keyid-format=long

Example output

Text
/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

Bash
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

Bash
git commit -S -m "feat: add user authentication module"
Always Sign Commits (Recommended)

Enable automatic signing for all commits

Bash
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

Bash
# -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

Bash
git verify-commit HEAD

# Verify a specific commit
git verify-commit abc1234def5678

Good signature output

Text
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

Bash
git verify-tag v1.0.0

Good tag signature

Text
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

Bash
git log --show-signature -1

Example log output with signature

Text
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 module
Adding Your Public Key to GitHub

Export your public key to paste into GitHub

Bash
# 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
Warning
Your GPG private key is irreplaceable. If you lose it, you permanently lose the ability to sign new commits and tags with that identity. Back it up securely — encrypted and stored in at least two separate physical locations (encrypted USB drive, password manager with secure note, etc.). Never store the unencrypted private key in cloud storage.

Export private key for secure backup

Bash
# 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

Bash
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