The 'gpg failed to sign the data' error with 'No secret key' occurs when Git tries to sign a commit but GPG cannot find the private key configured in your Git settings. This typically happens when your signing key ID is misconfigured, the key was never imported, or GPG is looking in the wrong keyring.
The "gpg failed to sign the data" error with "No secret key" indicates that GPG cannot locate the private key needed to create a cryptographic signature for your commit. Git invokes GPG to sign commits when `commit.gpgsign` is enabled or when you use `git commit -S`, but the key specified in `user.signingkey` doesn't exist in your GPG keyring. This error differs from "Unusable secret key" (which means the key exists but is expired or otherwise invalid). "No secret key" means GPG literally cannot find any matching private key material. The key ID in your Git config may be incorrect, the key may never have been imported to this machine, or you might be using the wrong GPG home directory. Common scenarios include setting up a new machine and forgetting to import your GPG keys, using a key ID format that GPG doesn't recognize, or having separate keyrings for different GPG versions (GPG 1.x vs 2.x).
First, check what signing key Git is configured to use:
# Check global signing key
git config --global user.signingkey
# Check local repository override
git config --local user.signingkey
# Check effective value (combines global + local)
git config user.signingkeyIf this returns a key ID, note it down. If it returns nothing but you're still getting the error, Git might be trying to use a default key based on your email address.
Also check if GPG signing is enabled:
git config commit.gpgsign
# Returns "true" if enabledCheck what keys actually exist in your GPG keyring:
# List all secret (private) keys
gpg --list-secret-keys --keyid-format=long
# Example output when keys exist:
# /home/user/.gnupg/pubring.kbx
# -----------------------------
# sec rsa4096/ABC123DEF456789AB 2023-01-15 [SC] [expires: 2025-01-15]
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# uid [ultimate] Your Name <[email protected]>
# ssb rsa4096/DEF789GHI123456CD 2023-01-15 [E]If this command returns no output or doesn't show the expected key, then the key hasn't been imported to this machine.
Compare the key ID from Git config with what's listed. Note that key IDs can appear in different formats:
- Short ID: Last 8 characters (e.g., 456789AB)
- Long ID: Last 16 characters (e.g., ABC123DEF456789AB)
- Fingerprint: Full 40 characters
If the key doesn't exist on this machine, you need to import it:
From a backup file:
# Import private key from backup
gpg --import private-key-backup.asc
# You'll be prompted for the key's passphraseFrom another machine:
# On the machine that has the key, export it:
gpg --export-secret-keys --armor YOUR_KEY_ID > private-key.asc
# Securely transfer the file to the new machine, then import:
gpg --import private-key.asc
# Delete the exported file after import
rm private-key.ascFrom a keyserver (public key only - won't help for signing):
# This only imports PUBLIC keys, not secret keys
# You cannot sign with just a public key
gpg --keyserver keyserver.ubuntu.com --recv-keys YOUR_KEY_IDAfter importing, verify the key appears:
gpg --list-secret-keys --keyid-format=longIf the key exists but Git can't find it, the ID format might be wrong:
# Get the correct long format key ID
gpg --list-secret-keys --keyid-format=long
# Look for the line starting with "sec" and note the ID after the slash
# sec rsa4096/ABC123DEF456789AB 2023-01-15 [SC]
# ^^^^^^^^^^^^^^^^^ This is your long key IDUpdate Git to use the correct key ID:
# Set using long format (recommended)
git config --global user.signingkey ABC123DEF456789AB
# Or use the full fingerprint (most reliable)
gpg --list-secret-keys --keyid-format=long --fingerprint
# Get the fingerprint (40-char string without spaces)
git config --global user.signingkey XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXTest the fix:
# Test GPG signing directly
echo "test" | gpg --clearsign
# Test a Git commit
git commit --allow-empty -S -m "Test signed commit"If you've never created a GPG key or need a new one:
# Generate a new GPG key pair
gpg --full-generate-key
# When prompted:
# - Key type: (1) RSA and RSA (default)
# - Key size: 4096 (recommended)
# - Expiration: 1y or 2y (recommended over no expiration)
# - Real name: Your Name
# - Email: [email protected] (must match Git config)
# - Passphrase: Choose a strong passphraseAfter generation, get your key ID:
gpg --list-secret-keys --keyid-format=long
# Note the ID after "sec rsa4096/"Configure Git to use it:
git config --global user.signingkey YOUR_NEW_KEY_ID
git config --global commit.gpgsign trueAdd the public key to GitHub/GitLab:
# Export public key
gpg --armor --export YOUR_KEY_ID
# Copy the output and add it to:
# GitHub: Settings > SSH and GPG keys > New GPG key
# GitLab: User Settings > GPG KeysGPG might be looking in the wrong directory for keys:
# Check current GPG home directory
gpgconf --list-dirs homedir
# Default is usually ~/.gnupg
# Check if GNUPGHOME environment variable is set
echo $GNUPGHOME
# List keys in a specific directory
gpg --homedir /path/to/.gnupg --list-secret-keysIf keys exist in a different location:
# Option 1: Set GNUPGHOME permanently in your shell profile
echo 'export GNUPGHOME="/correct/path/.gnupg"' >> ~/.bashrc
source ~/.bashrc
# Option 2: Copy keys to default location
cp -r /old/path/.gnupg/* ~/.gnupg/For Git specifically, you can also configure the GPG program:
# Tell Git which GPG to use
git config --global gpg.program gpg2
# Or specify full path
git config --global gpg.program /usr/bin/gpgDifferent GPG versions (1.x vs 2.x) use different keyring formats:
# Check installed GPG versions
which gpg gpg2
gpg --version
gpg2 --version 2>/dev/null
# List keys with each version
gpg --list-secret-keys
gpg2 --list-secret-keys 2>/dev/nullIf keys appear in one version but not the other:
# Export from the version that has keys
gpg --export-secret-keys --armor > keys-backup.asc
# Import to the version Git is using
gpg2 --import keys-backup.ascMake sure Git uses the correct GPG version:
# Check current GPG program setting
git config gpg.program
# Set to gpg2 if that's where your keys are
git config --global gpg.program gpg2
# Or explicitly use gpg (version 1.x)
git config --global gpg.program gpgIf GPG prompts work but Git signing fails, the GPG agent may need configuration:
# Ensure GPG agent is running
gpg-agent --daemon
# Set GPG_TTY for terminal-based passphrase prompts
export GPG_TTY=$(tty)
echo 'export GPG_TTY=$(tty)' >> ~/.bashrc
# Test that GPG agent works
echo "test" | gpg --clearsignFor GUI-based passphrase entry, install pinentry:
# Ubuntu/Debian
sudo apt install pinentry-gtk2
# or
sudo apt install pinentry-gnome3
# macOS
brew install pinentry-mac
# Configure GPG to use it
echo "pinentry-program /usr/bin/pinentry-gtk-2" >> ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agentFor macOS with GPG Suite:
echo "pinentry-program /usr/local/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agentIf you need to commit urgently while troubleshooting:
# Commit without signing (one-time)
git commit --no-gpg-sign -m "Your commit message"
# Disable signing globally (temporary)
git config --global commit.gpgsign false
# Disable signing for current repository only
git config commit.gpgsign falseRemember to re-enable signing once fixed:
git config --global commit.gpgsign trueFor CI/CD environments where signing isn't needed:
# .gitlab-ci.yml or GitHub Actions
env:
GIT_COMMITTER_NAME: CI Bot
GIT_COMMITTER_EMAIL: [email protected]
script:
- git config commit.gpgsign false
- git commit -m "Automated commit"### Understanding GPG Key Architecture
GPG keys have a hierarchical structure:
- Primary key: Used for certification (signing other keys)
- Subkeys: Used for signing, encryption, or authentication
When Git signs commits, it typically uses a signing subkey (marked [S]). If you export only the primary key or only certain subkeys, signing may fail.
# Show full key structure
gpg --list-secret-keys --keyid-format=long
# Look for [S] capability - that's the signing key
# sec rsa4096/ABC123... [SC] <- Primary key (Sign + Certify)
# ssb rsa4096/DEF456... [E] <- Encryption subkey
# ssb rsa4096/GHI789... [S] <- Signing subkey (this one signs commits)### Matching Keys to Email Addresses
If user.signingkey isn't set, GPG tries to find a key matching your Git email:
# Check Git email
git config user.email
# Key uid must contain this email
gpg --list-secret-keys [email protected]If emails don't match, either:
1. Set user.signingkey explicitly
2. Add the email as a uid to your key: gpg --edit-key KEYID then adduid
### SSH Signing (Alternative to GPG)
Git 2.34+ supports signing commits with SSH keys instead of GPG:
# Configure SSH signing
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
# Commits will now be signed with your SSH key
git commit -S -m "SSH-signed commit"This avoids GPG complexity entirely if you already have SSH keys set up.
### Troubleshooting Checklist
If still having issues, verify each step:
# 1. GPG works standalone
echo "test" | gpg --clearsign
# Should produce signed output
# 2. Correct key ID in Git config
git config user.signingkey
gpg --list-secret-keys --keyid-format=long | grep -i <that-id>
# Should find the key
# 3. Email matches
git config user.email
gpg --list-secret-keys
# Email in uid should match Git email
# 4. GPG agent running
pgrep gpg-agent
# Should return a PID
# 5. Correct GPG program
which $(git config gpg.program || echo gpg)
# Should exist and be executable### WSL (Windows Subsystem for Linux) Considerations
WSL has separate keyrings from Windows:
# Keys in Windows GPG are NOT visible in WSL
# You must import keys separately in WSL
# Option 1: Import to WSL
gpg --import /mnt/c/path/to/exported-key.asc
# Option 2: Use Windows GPG from WSL
git config --global gpg.program "/mnt/c/Program Files (x86)/GnuPG/bin/gpg.exe"### macOS Keychain Integration
On macOS with GPG Suite, you may need to configure keychain access:
# Install GPG Suite (includes pinentry-mac)
brew install --cask gpg-suite
# Configure pinentry
echo "pinentry-program /usr/local/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf
echo "use-agent" >> ~/.gnupg/gpg.conf
# Restart agent
gpgconf --kill gpg-agent
# Store passphrase in Keychain
echo "default-cache-ttl 600" >> ~/.gnupg/gpg-agent.conf
echo "max-cache-ttl 7200" >> ~/.gnupg/gpg-agent.conf### CI/CD Pipeline Configuration
For automated environments, you typically need to import keys at runtime:
# GitHub Actions example
- name: Import GPG key
run: |
echo "${{ secrets.GPG_PRIVATE_KEY }}" | gpg --import
git config --global user.signingkey ${{ secrets.GPG_KEY_ID }}
git config --global commit.gpgsign trueStore the key as a base64-encoded secret:
gpg --export-secret-keys --armor KEY_ID | base64 -w 0kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server
fatal: unable to access: Proxy auto-configuration failed
How to fix 'Proxy auto-configuration failed' in Git
fatal: unable to access: Authentication failed (proxy requires basic auth)
How to fix 'Authentication failed (proxy requires basic auth)' in Git
fatal: unable to access: no_proxy configuration not working
How to fix 'no_proxy configuration not working' in Git
fatal: unable to read tree object in treeless clone
How to fix 'unable to read tree object in treeless clone' in Git