This Git error occurs when you attempt to merge or pull with signature verification enabled, but one or more commits lack a GPG signature. Fix it by signing the commits or disabling signature verification for the operation.
When Git performs a merge or pull operation with the `--verify-signatures` flag (or with `merge.verifySignatures` set to true in your config), it checks that every commit being merged has a valid GPG signature. If any commit lacks a signature, Git refuses to proceed and displays this error. GPG (GNU Privacy Guard) signatures provide cryptographic proof that commits were made by the person who holds the corresponding private key. This is a security measure to prevent commits from being forged or tampered with. Many organizations and projects require signed commits to ensure code integrity. This error commonly appears when: - You're merging a branch containing unsigned commits - Your repository or CI pipeline has enabled signature verification - A branch protection rule requires signed commits - You're pulling from a remote with signature verification enabled
First, check which commits in your branch lack GPG signatures:
git log --show-signature HEAD~10..HEADUnsigned commits will show no signature information, while signed commits display:
commit abc1234...
gpg: Signature made Wed Jan 15 10:30:00 2025
gpg: Good signature from "Your Name <[email protected]>"To see just the signature status in a compact format:
git log --pretty=format:"%h %G? %s" HEAD~10..HEADThe %G? shows: G = good signature, N = no signature, B = bad signature.
Before signing commits, ensure GPG is properly set up:
# List your GPG keys
gpg --list-secret-keys --keyid-format=long
# Check Git's signing key configuration
git config --get user.signingkeyIf no key is configured, set it:
# Get your key ID from the gpg output (e.g., 3AA5C34371567BD2)
git config --global user.signingkey YOUR_KEY_IDAlso ensure your email matches the key:
git config --get user.emailConfigure Git to sign all commits by default so you don't need to remember the -S flag:
# Enable globally
git config --global commit.gpgsign true
# Or for just this repository
git config commit.gpgsign trueNow all new commits will be automatically signed with your GPG key.
If you need to sign commits that were already made, use interactive rebase:
# Rebase the last N commits (replace 5 with your count)
git rebase -i HEAD~5 --exec "git commit --amend --no-edit -S"This replays each commit and signs it. Note that this rewrites history, so:
- Only do this on branches that haven't been pushed, OR
- You'll need to force push afterward: git push --force-with-lease
For all commits since branching from main:
git rebase -i main --exec "git commit --amend --no-edit -S"If signature verification is optional and you need to merge quickly:
# Merge without verifying signatures
git merge branch-name --no-verify-signatures
# Pull without verification
git pull --no-verify-signaturesIf merge.verifySignatures is set in your config, temporarily override it:
git -c merge.verifySignatures=false merge branch-nameNote: This bypasses signature verification for this operation only. If your organization requires signed commits, you should sign them instead.
If GitHub's branch protection requires signed commits but your PR contains unsigned commits, you can use squash merge:
1. Go to the pull request on GitHub
2. Click the dropdown arrow next to "Merge pull request"
3. Select "Squash and merge"
GitHub will create a single new commit signed by GitHub's web-flow key, which satisfies the signed commits requirement.
Important: Regular "Rebase and merge" won't work because GitHub creates new unsigned commits during that process.
### GPG Agent and Passphrase Caching
If you're prompted for your GPG passphrase repeatedly, configure gpg-agent to cache it:
# ~/.gnupg/gpg-agent.conf
default-cache-ttl 3600
max-cache-ttl 86400Restart the agent:
gpgconf --kill gpg-agent### Signing Merge Commits
When merging with --verify-signatures, you can also sign the merge commit itself:
git merge --verify-signatures -S feature-branchThis both verifies incoming signatures AND signs the resulting merge commit.
### CI/CD Pipeline Signing
In CI environments, you'll need to:
1. Import your GPG private key securely (use secrets management)
2. Configure Git with the key ID
3. Ensure the GPG agent can run non-interactively
Example GitHub Actions snippet:
- name: Import GPG key
run: |
echo "${{ secrets.GPG_PRIVATE_KEY }}" | gpg --batch --import
git config --global user.signingkey ${{ secrets.GPG_KEY_ID }}
git config --global commit.gpgsign true### SSH Signing (Git 2.34+)
As an alternative to GPG, Git 2.34+ supports SSH key signing:
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pubThis uses your existing SSH key for signing, which is simpler than managing GPG keys.
### Verifying Signatures From GitHub Web Interface
Commits made directly on GitHub (via the web interface, squash merges, or merge button) are signed by GitHub's internal key. To verify these locally, add GitHub's public key to your GPG keyring:
curl https://github.com/web-flow.gpg | gpg --import### Common GPG Troubleshooting
If signing fails with "gpg failed to sign the data":
# Ensure GPG can access TTY
export GPG_TTY=$(tty)
# Test GPG is working
echo "test" | gpg --clearsign
# On macOS with pinentry issues
brew install pinentry-mac
echo "pinentry-program /usr/local/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.confkex_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