Git GPG Signing
Comprehensive guidance for setting up, configuring, and troubleshooting GPG commit signing across all platforms.
Table of Contents
-
Overview
-
When to Use This Skill
-
Quick Start
-
Platform-Specific Setup
-
Key Generation
-
Git Configuration
-
Passphrase Caching
-
GitHub Integration
-
Troubleshooting
-
GPG Signing Methods Comparison
-
Security Best Practices
-
Resources
-
Related Skills
Overview
Git commit signing provides cryptographic proof that commits came from you. This skill helps you:
-
Install and configure GPG tools on Windows, macOS, and Linux
-
Set up commit signing with proper key management
-
Configure passphrase caching for better workflow
-
Troubleshoot common GPG signing issues
-
Understand security trade-offs and best practices
When to Use This Skill
This skill should be used when:
-
Setting up GPG commit signing for the first time
-
Configuring GPG tools (Gpg4win, GPG Suite, gnupg)
-
Troubleshooting GPG signing errors ("gpg: signing failed", "inappropriate ioctl", etc.)
-
Troubleshooting keyboxd daemon startup issues (Windows race condition)
-
Determining which GPG installation Git is using
-
Understanding Windows daemon startup behavior vs. official design
-
Configuring passphrase caching to reduce prompts
-
Understanding GPG vs SSH vs S/MIME signing methods
-
Adding GPG keys to GitHub/GitLab/Bitbucket
-
Resolving "Unverified" commits on GitHub
-
Working with .gnupg/gpg-agent.conf configuration
Quick Start
Basic Setup (Single Personal Key):
1. Install GPG (see Platform-Specific Setup below)
2. Generate key
gpg --full-generate-key
Select: (9) ECC (sign and encrypt) → Curve 25519
Expiration: 0 (no expiration)
Passphrase: Strong 20+ character passphrase
3. Get key ID
gpg --list-secret-keys --keyid-format=long
Look for "sec ed25519/<KEY_ID>"
4. Configure Git
git config --global user.signingkey <KEY_ID> git config --global commit.gpgsign true
5. Export public key and add to GitHub
gpg --armor --export <KEY_ID>
Paste at: https://github.com/settings/keys
Platform-Specific Setup
Windows: Gpg4win Installation
For detailed Windows setup, see references/windows-setup.md.
Quick install:
Option 1: Download installer
https://gpg4win.org/thanks-for-download.html
Option 2: winget
winget install --id GnuPG.Gpg4win -e --source winget
Configure Git to use Gpg4win (adjust path if installed elsewhere)
git config --global gpg.program "C:/Program Files (x86)/GnuPG/bin/gpg.exe"
macOS: GPG Suite / Homebrew
Option 1: Homebrew (recommended)
brew install gnupg
Option 2: GPG Suite
Download from: https://gpgtools.org/
Configure Git (if needed)
git config --global gpg.program $(which gpg)
Linux: GnuPG
Debian/Ubuntu
sudo apt update && sudo apt install gnupg
Fedora/RHEL
sudo dnf install gnupg2
Arch
sudo pacman -S gnupg
WSL: Follow Linux Instructions
WSL users: Follow the Linux setup instructions above (WSL runs Linux). See troubleshooting section for WSL-specific issues if needed.
Key Generation
Personal Development Key (Interactive)
Generate key interactively
gpg --full-generate-key
Follow prompts:
1. Key type: (9) ECC (sign and encrypt) default
2. Curve: (1) Curve 25519 default
3. Expiration: 0 = no expiration (or 2y for 2 years)
4. Real name: Your Name
5. Email: your.verified@email.com
6. Comment: (optional, can leave blank)
7. Passphrase: Strong 20+ character passphrase
List keys to get KEY_ID
gpg --list-secret-keys --keyid-format=long
Look for "sec ed25519/<KEY_ID>"
Recommended algorithm: EdDSA using Curve25519 (Ed25519) - modern, fast, small keys, excellent security
Alternative: RSA 4096-bit (traditional, widely compatible)
Exporting Keys
Export public key (for GitHub)
gpg --armor --export <KEY_ID>
Export private key (for backup only - KEEP SECURE!)
gpg --armor --export-secret-keys <KEY_ID>
Git Configuration
Enable Commit Signing
Global (all repositories)
git config --global user.signingkey <KEY_ID> git config --global commit.gpgsign true git config --global tag.gpgSign true
Repository-local (specific repo)
cd /path/to/repo git config user.signingkey <KEY_ID> git config commit.gpgsign true
Verify Configuration
Check configured key
git config --global user.signingkey
Test signing
git commit --allow-empty -m "Test GPG signing"
Verify signature
git log --show-signature -1
Passphrase Caching
GPG agent caches passphrases to reduce how often you're prompted.
Check if config exists:
ls ~/.gnupg/gpg-agent.conf
Create or edit ~/.gnupg/gpg-agent.conf :
Cache passphrase for 8 hours of inactivity
default-cache-ttl 28800
Maximum cache time of 24 hours regardless of use
max-cache-ttl 86400
Allow pinentry to cache the passphrase
allow-preset-passphrase
Apply changes:
gpgconf --kill gpg-agent gpgconf --launch gpg-agent
For comprehensive caching configuration, including security scenarios, testing procedures, and troubleshooting, see references/passphrase-caching.md.
Windows-Specific: Dual GPG Installation Issue
CRITICAL for Windows users: Windows typically has two separate GPG installations (Gpg4win and Git Bash GPG), each with different config file locations:
-
Gpg4win: %APPDATA%\gnupg\gpg-agent.conf (typically C:\Users<Username>\AppData\Roaming\gnupg\gpg-agent.conf )
-
Git Bash GPG: ~/.gnupg/gpg-agent.conf (resolves to C:\Users<Username>.gnupg\gpg-agent.conf )
Common problem: Configuring ~/.gnupg/gpg-agent.conf (Git Bash GPG) when Git is configured to use Gpg4win. Result: configuration silently ignored, caching doesn't work.
Verify which GPG Git is using:
Check Git's GPG configuration
git config --global gpg.program
If output is "C:/Program Files (x86)/GnuPG/bin/gpg.exe":
→ Use: %APPDATA%\gnupg\gpg-agent.conf
Verify GPG's config directory
gpgconf --list-dirs homedir
Windows configuration must include pinentry-program:
Example: %APPDATA%\gnupg\gpg-agent.conf
default-cache-ttl 28800 max-cache-ttl 86400 allow-preset-passphrase
REQUIRED for Windows:
pinentry-program C:/Program Files (x86)/GnuPG/bin/pinentry-basic.exe
See: Windows Setup Guide - Dual GPG Installations for detailed explanation.
Recommended Cache Durations
Scenario default-cache-ttl max-cache-ttl Rationale
High Security 900 (15 min) 3600 (1 hour) Prompt frequently, short window
Balanced 3600 (1 hour) 28800 (8 hours) Prompt every ~hour, expires by end of day
Convenience 28800 (8 hours) 86400 (24 hours) Prompt once per workday, expires daily
GitHub Integration
Adding GPG Key to GitHub
Export public key:
gpg --armor --export <KEY_ID>
Add to GitHub:
-
Click "New GPG key"
-
Paste ASCII-armored public key
-
Click "Add GPG key"
Verify email matches:
-
Git email must match GPG key email
-
Email must be verified in GitHub account
Check Git email
git config --global user.email
Check GPG key email
gpg --list-keys <KEY_ID>
Troubleshooting "Unverified" Commits
Possible causes:
-
Public key not added to GitHub → Add key at Settings → SSH and GPG keys
-
Email mismatch → Ensure Git email = GPG key email = GitHub verified email
-
Key expired → Extend expiration or generate new key
-
Key revoked → Generate new key (cannot un-revoke)
Troubleshooting
For comprehensive troubleshooting, see references/troubleshooting.md.
"gpg: signing failed: No secret key"
Cause: Git configured to use key ID that doesn't exist in keyring.
Solution:
List available keys
gpg --list-secret-keys --keyid-format=long
Verify Git config matches available key
git config --global user.signingkey
If mismatch, update config
git config --global user.signingkey <CORRECT_KEY_ID>
"gpg: signing failed: Inappropriate ioctl for device"
Cause: GPG agent cannot prompt for passphrase (terminal issue).
Solution (Linux/macOS/WSL):
Set GPG_TTY environment variable
export GPG_TTY=$(tty)
Add to shell profile (e.g., ~/.bashrc, ~/.zshrc)
echo 'export GPG_TTY=$(tty)' >> ~/.bashrc
Solution (Windows with Gpg4win):
Use GUI pinentry (adjust path to match your Gpg4win installation)
echo 'pinentry-program "C:/Program Files (x86)/GnuPG/bin/pinentry-basic.exe"' >> ~/.gnupg/gpg-agent.conf gpgconf --kill gpg-agent
"error: gpg failed to sign the data"
Debug steps:
Test GPG signing directly
echo "test" | gpg --clearsign
Check GPG agent status
gpgconf --list-components
Check key expiration
gpg --list-keys --keyid-format=long <KEY_ID>
Restart GPG agent
gpgconf --kill gpg-agent gpgconf --launch gpg-agent
Try commit again
git commit -m "test"
Passphrase Prompt Every Commit (Cache Not Working)
Windows users: This is commonly caused by dual GPG installation issues. See Windows Setup - Passphrase Caching Troubleshooting and Troubleshooting - Windows Caching Issue for detailed diagnosis.
Possible causes:
Wrong config file location (Windows):
Verify which GPG Git is using
git config --global gpg.program
Check GPG's config directory
gpgconf --list-dirs homedir
Ensure config exists at correct location
Windows (Gpg4win): %APPDATA%\gnupg\gpg-agent.conf
Windows (Git Bash): ~/.gnupg/gpg-agent.conf
Linux/macOS/WSL: ~/.gnupg/gpg-agent.conf
gpg-agent.conf not loaded:
Restart agent to load config
gpgconf --kill gpg-agent gpgconf --launch gpg-agent
Verify config loaded
gpgconf --list-options gpg-agent | grep cache-ttl
Cache TTL set too low → Increase cache time in ~/.gnupg/gpg-agent.conf
Multiple GPG agents running:
Kill all agents
pkill gpg-agent
Launch single agent
gpgconf --launch gpg-agent
GPG Signing Methods Comparison
Method Best For Setup Complexity Key Management
GPG Full-featured, supports expiration/revocation Medium Most flexible
SSH Simplest, reuses existing SSH keys Low Limited features
S/MIME Enterprise with X.509 certificates High Org-managed
SSH Signing (Alternative)
When to use SSH instead of GPG:
-
Simple personal projects
-
Already have SSH key setup
-
Don't need expiration/revocation features
-
Want minimal configuration
Setup:
Configure Git to use SSH signing
git config --global gpg.format ssh git config --global user.signingkey ~/.ssh/id_ed25519.pub git config --global commit.gpgsign true
Add SSH key to GitHub as "Signing Key"
Limitations:
-
No key expiration support
-
No revocation tracking
-
Requires Git 2.34+ (2021)
Security Best Practices
For comprehensive security guidance, see references/security-best-practices.md.
Quick recommendations:
-
✅ Use passphrase protection on personal keys (minimum 20 characters)
-
✅ Configure caching to balance security and convenience (4-8 hours)
-
✅ Consider key expiration: No expiration for personal projects, 1-year for enterprise work
-
✅ Backup private key to encrypted vault or password manager's Secure Documents
-
⚠️ Never store unencrypted keys in Git repos, cloud storage, or email
Resources
Reference Documentation
-
Quick Command Reference - Quick lookup for common GPG and Git signing commands
-
Windows Setup Guide - Gpg4win installation, Git Bash paths, security considerations
-
Passphrase Caching Configuration - Cache strategies, security trade-offs
-
Security Best Practices - Passphrase protection, key expiration, backup strategies
-
Troubleshooting Guide - Common issues and solutions
-
GPG Agent Configuration Example - Sample configuration file
-
Test Scenarios - Skill activation validation scenarios
Official Documentation
-
GitHub: Managing commit signature verification
-
GnuPG Documentation
-
Git Documentation: Signing Your Work
Related Skills
-
git-commit: Use for complete git commit workflow with Conventional Commits format, safety protocols, and attribution requirements
-
git-identity: Use for multi-identity GPG key isolation -- scoping different GPG keys to different directories using includeIf conditional includes
-
config: Advanced Git configuration including aliases, credentials, and performance tuning
-
setup: Prerequisite for Git installation and configuration
Version History
-
v1.1.1 (2025-11-25): Progressive disclosure optimization - extracted Test Scenarios to reference file, removed redundant Quick Command Reference section, reduced SKILL.md to under 500 lines
-
v1.1.0 (2025-11-22): Enhanced troubleshooting - added keyboxd daemon race condition troubleshooting (T7777/T7829), dynamic GPG detection workflow, Windows startup best practices with official design vs. reality analysis
-
v1.0.5 (2025-11-19): Optimization improvements - added table of contents to SKILL.md, extracted Essential Commands Reference to quick-reference.md, reduced line count from 530 to 522
-
v1.0.4 (2025-11-17): Progressive disclosure improvement - extracted Security Best Practices to separate reference file
-
v1.0.3 (2025-11-17): Validated against official documentation - fixed tag.gpgSign capitalization, updated Last Verified dates
-
v1.0.2 (2025-11-12): Enhanced documentation - added TOCs to long references, documented test scenarios
-
v1.0.1 (2025-11-13): Added cross-reference to git-commit skill
-
v1.0.0 (2025-01-09): Initial release migrated from repository documentation
Last Updated
Date: 2025-11-28 Model: claude-opus-4-5-20251101