
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
If you cannot cryptographically prove who wrote a line of code, your repository is vulnerable to impersonation and supply chain attacks. Learning to sign your Git commits with GPG or SSH is the definitive way to bind identity to history, ensuring that every change in your audit trail is authentic. This practice is no longer optional for teams pursuing SOC 2 or ISO 27001 compliance; it is a fundamental control for shifting security left and establishing trust in your software delivery lifecycle.
git config --global commit.gpgsign true. Use SSH keys (Ed25519) for simpler management and native Git 2.34+ support, or GPG for broader legacy compatibility and strict compliance requirements.How do you generate and configure keys to sign your Git commits with GPG or SSH?
The first step in securing your commit history is generating a dedicated cryptographic key. While GPG has been the standard for decades, SSH signing (available since Git 2.34) offers a streamlined alternative that reuses existing authentication infrastructure. Both methods achieve the same goal: binding your identity to a specific commit object via a digital signature.
Generating an SSH Key for Signing
SSH signing is generally recommended for new setups in 2026 due to lower friction. You should use the Ed25519 algorithm for its superior performance and security profile compared to RSA.
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/git_signing_key After generation, copy the public key to your clipboard and add it to your Git provider's "Signing Keys" section (distinct from authentication keys on some platforms).
cat ~/.ssh/git_signing_key.pub | pbcopy # macOS
# or
cat ~/.ssh/git_signing_key.pub | xclip -selection clipboard # Linux Generating a GPG Key for Signing
If your organization requires GPG for compliance evidence collection, generate a modern RSA-4096 or ECC key. Avoid SHA-1; ensure your digest algorithm is SHA-512.
gpg --full-generate-key
# Select: (1) RSA and RSA
# Key size: 4096
# Validity: 2y (rotate annually)
# Name/Email: Match your git config exactly Export the ASCII-armored public key for upload:
gpg --armor --export [email protected] > my_gpg_public.asc Configuring Git Globally
Once your key exists locally and remotely, tell Git to use it. Consistency between your user.email and the key's email is mandatory; mismatches result in unverified badges even if the signature is cryptographically valid.
- For SSH: Set format to ssh, specify the signing key path, and enable auto-signing.
- For GPG: Set format to openpgp, provide the key ID, and configure the gpg program path if non-standard.
# SSH Configuration
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/git_signing_key
git config --global commit.gpgsign true
# GPG Configuration
git config --global gpg.format openpgp
git config --global user.signingkey YOUR_GPG_KEY_ID
git config --global commit.gpgsign true GPG vs SSH signing: which method should you choose for commit verification?
Choosing between GPG and SSH depends on your team's maturity, tooling ecosystem, and compliance obligations. There is no universal "best," only the right trade-off for your context. In my experience helping Nepal-based outsourcing firms align with global clients, SSH adoption has accelerated significantly since 2024 because it eliminates the separate key management overhead that often causes developer friction.
| Criteria | SSH Signing | GPG Signing |
|---|---|---|
| Setup Complexity | Low (reuses existing keys) | High (separate keyring, agents) |
| Algorithm Support | Ed25519, RSA, ECDSA | RSA, ECC, DSA (legacy) |
| Git Version Requirement | ≥ 2.34.0 | All versions |
| Platform Support | GitHub, GitLab, Bitbucket (2026) | Universal |
| Key Rotation | Simple (add new, revoke old) | Complex (web of trust, revocation certs) |
| Compliance Acceptance | Growing (check auditor preference) | Gold Standard |
| Tag Signing | Supported | Supported |
If you are starting fresh or migrating a team that already uses SSH for authentication, choose SSH. It reduces cognitive load and operational toil. Reserve GPG for environments where external auditors explicitly demand OpenPGP artifacts or where you need to integrate with legacy PKI systems. For most DevOps teams practicing supply chain security, SSH provides sufficient cryptographic assurance with significantly less maintenance burden.
How do you troubleshoot unverified signatures and common signing failures?
A "Unverified" badge on a signed commit usually indicates a configuration mismatch rather than a cryptographic failure. The most frequent cause in my practice is an email address discrepancy. Git matches signatures against the committer email, not just the key owner. If your local user.email differs by capitalization or domain alias from what is registered on the platform, verification fails silently.
Diagnosing Signature Issues Locally
Before pushing, verify your signature locally using git log --show-signature. This outputs the raw GPG/SSH status. Look for "Good signature" and confirm the UID matches your expected identity.
git log --show-signature -1
# Expected output includes:
# gpg: Good signature from "Your Name <[email protected]>"
# or for SSH:
# Good "git" signature for [email protected] with ED25519 key SHA256:... Fixing Email Mismatches
If signatures fail verification despite being cryptographically valid, audit your email configuration across all layers:
- Check
git config user.email(local and global). - Verify the email listed in your GPG UID (
gpg --list-keys) or SSH key comment. - Confirm the exact email string added to your Git provider's signing keys page.
- Ensure no noreply aliases are interfering if you've configured privacy emails.
For GPG specifically, ensure your key hasn't expired. Expired keys produce valid signatures that platforms reject. Extend validity with gpg --edit-key KEY_ID then expire. For SSH, verify you haven't accidentally added the key as an "Authentication Key" instead of a "Signing Key" on platforms that distinguish them.
Handling Passphrase Fatigue
Developers often disable signing because entering passphrases repeatedly breaks flow. Solve this with agent caching, never by removing passphrases. Configure gpg-agent to cache credentials for a reasonable duration (e.g., 4 hours) or use hardware tokens like YubiKey which require physical touch but no passphrase entry. For SSH, ssh-add --apple-use-keychain (macOS) or equivalent keychain integrations provide similar relief.
How do you enforce signed commits in CI pipelines and branch protection?
Signing commits individually is insufficient; you must enforce verification at the gate. Without enforcement, unsigned commits from compromised accounts or careless scripts can pollute your history. Branch protection rules and CI checks transform signing from a personal habit into an organizational control aligned with secure development practices.
Configuring Branch Protection Rules
On GitHub, navigate to Settings → Branches → Add Rule. Enable "Require signed commits." This prevents merging any commit lacking a verified signature. Apply this to main, release/*, and any protected deployment branches. GitLab and Bitbucket offer equivalent controls under repository settings.
Warning: Enable this only after confirming all active contributors have configured signing. Enabling prematurely blocks legitimate work and creates emergency override pressure. Communicate the change window clearly.
CI Pipeline Verification Gates
Branch protection stops merges, but CI should catch issues earlier. Add a pipeline job that validates signatures before running expensive tests. This provides fast feedback and generates audit artifacts.
# Example GitLab CI job for signature verification
verify-signatures:
stage: validate
script:
- git log --format="%H %G?" origin/main..HEAD | grep -v "G$" && exit 1 || echo "All commits verified"
allow_failure: false For automated releases, ensure your CI bot also signs commits. Generate a dedicated machine identity (SSH key or GPG key) stored in your secrets manager. Never reuse human keys for automation. Document this machine identity in your compliance evidence to satisfy auditor inquiries about non-human actors.
Establishing Trust Through Verified Commit History
Cryptographic commit signing transforms your repository from a mutable ledger into a verifiable chain of custody. Whether you choose SSH for operational simplicity or GPG for compliance alignment, the critical factor is consistent enforcement. Start by configuring your local environment today, then progressively roll out branch protection as your team builds muscle memory. Remember that signing is one layer of defense; combine it with secrets scanning and dependency auditing for comprehensive supply chain security. If you need help designing a compliant Git workflow or auditing your existing signing infrastructure, reach out to discuss your specific requirements.