Git Notes
Learn to sign Git commits with GPG keys to prove authenticity. Set up GPG signing, configure GitHub verification, and understand commit trust.
Here is a scary thought: anyone in the world can run git config user.name "Linus Torvalds" and git config user.email "torvalds@linux-foundation.org" on their machine and start making commits that appear to be from the creator of Git himself. Git does not verify identity by default. The author information in a commit is purely self-reported.
Commit signing solves this problem by adding a cryptographic signature to each commit that proves it genuinely came from the claimed author. When you push signed commits to GitHub, they display a green "Verified" badge, giving your teammates and the open-source community confidence that the code truly came from you.
Why Sign Commits?
In professional environments, commit signing serves several critical purposes:
- Identity verification: Proves commits actually came from the claimed author
- Tamper detection: Any modification to the commit invalidates the signature
- Compliance requirements: Many regulated industries require signed commits for audit trails
- Supply chain security: Prevents attackers from injecting malicious code under someone else's name
- Trust in open source: Maintainers can verify contributions are genuine
Setting Up GPG Signing
Step 1: Generate a GPG Key
# Generate a new GPG key pair
gpg --full-generate-key
# When prompted:
# - Key type: RSA and RSA (option 1)
# - Key size: 4096 bits
# - Expiration: 0 (no expiry) or set a reasonable expiry
# - Real name: Your Name (must match your Git config)
# - Email: your-email@example.com (must match your GitHub email)
# - Passphrase: Choose a strong passphraseStep 2: Find Your Key ID
gpg --list-secret-keys --keyid-format=long/home/user/.gnupg/secring.gpg
------------------------------
sec rsa4096/ABC123DEF456GHI7 2024-01-15 [SC]
1234567890ABCDEF1234567890ABCDEF12345678
uid [ultimate] Jane Doe <jane@example.com>
ssb rsa4096/XYZ789UVW012STU3 2024-01-15 [E]The key ID is the part after rsa4096/ — in this case ABC123DEF456GHI7.
Step 3: Configure Git to Use Your Key
# Tell Git which key to use for signing
git config --global user.signingkey ABC123DEF456GHI7
# Auto-sign ALL commits (recommended)
git config --global commit.gpgsign true
# Auto-sign ALL tags
git config --global tag.gpgsign trueStep 4: Add Your Public Key to GitHub
# Export your public key in ASCII armor format
gpg --armor --export ABC123DEF456GHI7-----BEGIN PGP PUBLIC KEY BLOCK----- mQINBGWExxxxx... (long block of text) ... -----END PGP PUBLIC KEY BLOCK-----
Copy the entire output (including the BEGIN and END lines) and add it at: GitHub → Settings → SSH and GPG keys → New GPG key
Making Signed Commits
With commit.gpgsign = true, every commit is automatically signed:
# Automatic signing (with gpgsign=true configured)
git commit -m "feat: add payment processing"
# Explicit signing for a single commit
git commit -S -m "feat: add payment processing"
# Sign a commit without gpgsign enabled globally
git commit -S -m "security: patch authentication bypass"Verifying Signatures
# Verify the last commit's signature
git log --show-signature -1commit a1b2c3d4e5f6 (HEAD -> main)
gpg: Signature made Mon Jan 15 10:30:00 2024 UTC
gpg: using RSA key 1234567890ABCDEF...
gpg: Good signature from "Jane Doe <jane@example.com>" [ultimate]
Author: Jane Doe <jane@example.com>
Date: Mon Jan 15 10:30:00 2024 +0000
feat: add payment processing# Verify all commits in a range
git log --show-signature main..feature/auth
# Show verification status in one-line format
git log --pretty="format:%H %G? %aN %s" -5
# G = Good signature, B = Bad, U = Untrusted, N = No signatureSSH Signing (Modern Alternative)
Starting with Git 2.34, you can sign commits using your existing SSH key instead of GPG:
# Configure SSH signing
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
# Create an allowed signers file for verification
echo "your-email@example.com $(cat ~/.ssh/id_ed25519.pub)" > ~/.config/git/allowed_signers
git config --global gpg.ssh.allowedSignersFile ~/.config/git/allowed_signersSSH signing is simpler to set up if you already have SSH keys configured for GitHub authentication.
Requiring Signed Commits via Branch Protection
Organizations can enforce signing through branch protection rules:
This is particularly important for:
- Production branches in regulated industries
- Open-source projects with many contributors
- Security-critical repositories
Signing Tags for Releases
Tags represent releases and are even more important to sign than individual commits:
# Create a signed annotated tag
git tag -s v1.0.0 -m "Release version 1.0.0"
# Verify a signed tag
git tag -v v1.0.0object a1b2c3d4e5f6... type commit tag v1.0.0 tagger Jane Doe <jane@example.com> 1705312200 +0000 Release version 1.0.0 gpg: Signature made Mon Jan 15 10:30:00 2024 UTC gpg: Good signature from "Jane Doe <jane@example.com>" [ultimate]
Troubleshooting Common Issues
# "gpg failed to sign the data"
# Fix: Tell GPG which terminal to use for passphrase
export GPG_TTY=$(tty)
# Add to ~/.bashrc or ~/.zshrc permanently
echo 'export GPG_TTY=$(tty)' >> ~/.zshrc
# "No secret key" error
# Verify your key ID matches what Git expects
git config user.signingkey
gpg --list-secret-keys --keyid-format=long
# Key expired
gpg --edit-key ABC123DEF456GHI7
gpg> expire # Set new expiration
gpg> saveCommon Mistakes
Mistake 1: Using an email for your GPG key that does not match your GitHub email. GitHub will not show the "Verified" badge unless the GPG key email matches a verified email on your account.
Mistake 2: Forgetting to re-sign after rebase. Rebasing creates new commits with new hashes, invalidating previous signatures. With commit.gpgsign=true, new commits are automatically signed during rebase.
Mistake 3: Not backing up your GPG key. If you lose your private key, you cannot sign new commits matching your old signatures. Export and securely store your private key.
Interview Questions
Q1: Why should you sign commits?
Without signing, anyone can set their Git user.name and user.email to impersonate another developer. Commit signing provides cryptographic proof of authorship, tamper detection, and compliance with audit requirements. GitHub shows "Verified" badges on properly signed commits.
Q2: What does the "Verified" badge mean on GitHub?
It means the commit was signed with a GPG, SSH, or S/MIME key registered to the committer's GitHub account, and the signature is valid. It proves the commit genuinely came from the account owner and was not modified after signing.
Q3: What is the difference between GPG and SSH signing?
Both provide cryptographic verification. GPG uses dedicated signing keys with a web of trust model and key servers. SSH signing (Git 2.34+) reuses your existing SSH keys, making setup simpler. GPG offers more features like key revocation certificates and subkeys.
Q4: Can you require signed commits via branch protection?
Yes. Enable "Require signed commits" in branch protection rules. Unsigned commits and commits with invalid signatures will be rejected when pushed to the protected branch.
Q5: Do you need to re-sign commits after rebasing?
Yes. Rebase creates entirely new commit objects with different SHA hashes, invalidating the original signatures. If commit.gpgsign=true is configured, Git automatically signs the new commits during the rebase process.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Signed Commits - Verify Commit Authenticity with GPG.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Git & GitHub topic.
Search Terms
git-github, git & github, git, github, security, signed, commits, signed commits - verify commit authenticity with gpg
Related Git & GitHub Topics