Skip to content

Instantly share code, notes, and snippets.

@juancsr
Last active September 23, 2026 15:29
Show Gist options
  • Select an option

  • Save juancsr/2935928f7495694a0ace786c3763542d to your computer and use it in GitHub Desktop.

Select an option

Save juancsr/2935928f7495694a0ace786c3763542d to your computer and use it in GitHub Desktop.
Signing Git commits with GPG on macOS (Apple Silicon)

Signing Git commits with GPG on macOS (Apple Silicon)

A complete, tested walkthrough for creating a GPG key, adding it to GitHub, and fixing the gpg: signing failed: No pinentry error that Homebrew users hit on M-series Macs.

Tested on macOS with Homebrew at /opt/homebrew (Apple Silicon). On Intel Macs, replace /opt/homebrew with /usr/local everywhere below.


1. Install GnuPG and pinentry-mac

pinentry-mac is the dialog that prompts for your key passphrase. GnuPG does not install it for you, and without it every signing attempt fails with No pinentry.

brew install gnupg pinentry-mac
gpg --version
ls -l /opt/homebrew/bin/pinentry-mac   # must exist before continuing

2. Generate the key

gpg --full-generate-key

Answer the prompts:

Prompt Answer
Key type 1 (RSA and RSA)
Key size 4096
Expiration 1y or 2y — renewable later with gpg --edit-key
Real name Your name
Email A verified email on your GitHub account
Passphrase Strong; store it in your password manager

The email is the part people get wrong. If it isn't verified under GitHub → Settings → Emails, GitHub will either reject the key or mark your commits Unverified.

3. Find your key ID

gpg --list-secret-keys --keyid-format=long
sec   rsa4096/3AA5C34371567BD2 2026-09-22 [SC]
      6D1D059002F640C0E123DAEF4158EA7997AC2E29
uid                 [ultimate] Your Name <you@example.com>

The key ID is the part after the slash on the sec line — 3AA5C34371567BD2 here. Export it for convenience:

export KEYID=3AA5C34371567BD2

4. Add the public key to GitHub

gpg --armor --export "$KEYID" | pbcopy

Then go to GitHub → Settings → SSH and GPG keys → New GPG key and paste. The pasted block must include both the -----BEGIN PGP PUBLIC KEY BLOCK----- and -----END PGP PUBLIC KEY BLOCK----- lines.

5. Configure Git

git config --global user.signingkey "$KEYID"
git config --global commit.gpgsign true
git config --global tag.gpgsign true
git config --global gpg.program "$(which gpg)"

Make sure the commit email matches the key's email exactly:

git config --global user.email    # must equal the UID email from step 3

6. Point gpg-agent at pinentry-mac

echo "pinentry-program /opt/homebrew/bin/pinentry-mac" > ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agent

gpg-agent only reads this file at startup, so the --kill is not optional — it respawns on the next use with the new config.

GnuPG also refuses to run with loose permissions:

chmod 700 ~/.gnupg
chmod 600 ~/.gnupg/*

7. Export GPG_TTY

echo 'export GPG_TTY=$(tty)' >> ~/.zshrc
source ~/.zshrc

Use ~/.zshrc, not ~/.zprofile. .zprofile only runs for login shells, so tmux panes, editor terminals, and plain zsh subshells would inherit a stale or empty GPG_TTY. $(tty) has to be re-evaluated per shell.

8. Verify

echo test | gpg --clearsign      # should pop the passphrase dialog
git commit --allow-empty -m "test: verify gpg signing"
git log --show-signature -1      # should print "Good signature"

After pushing, GitHub shows a green Verified badge next to the commit.


Troubleshooting

gpg: signing failed: No pinentry

[GNUPG:] KEY_CONSIDERED 6D1D059002F640C0E123DAEF4158EA7997AC2E29 2
[GNUPG:] BEGIN_SIGNING H8
gpg: signing failed: No pinentry

KEY_CONSIDERED means GPG found your key fine — the failure is purely that gpg-agent could not launch the passphrase dialog. Work through these in order:

  1. The binary isn't installed. This is the usual cause, even when gpg-agent.conf looks correct. Check with ls -l /opt/homebrew/bin/pinentry-mac; if it's missing, brew install pinentry-mac.
  2. Wrong Homebrew prefix. Guides written for Apple Silicon use /opt/homebrew/bin; on Intel Macs it's /usr/local/bin. Confirm the real path with which pinentry-mac and put that in the config.
  3. Agent not restarted. Run gpgconf --kill gpg-agent after any edit to ~/.gnupg/gpg-agent.conf.
  4. Invisible characters in the config. Run cat -A ~/.gnupg/gpg-agent.conf; you should see exactly pinentry-program /opt/homebrew/bin/pinentry-mac$ with no ^M and no trailing spaces.
  5. Still failing? Run gpg-agent --daemon --verbose in a second terminal to see which binary it tries to execute and why the exec fails.

error: gpg failed to sign the data with no No pinentry line

Usually a missing or stale GPG_TTY — see step 7, and note that adding the export to a shell config does not affect terminals that are already open.

Commit shows Unverified on GitHub

The committer email doesn't match a verified GitHub email that is also on the key's UID. Check all three: git config user.email, the UID from gpg --list-secret-keys, and GitHub → Settings → Emails.

Passphrase prompt on every single commit

Cache it for longer by adding to ~/.gnupg/gpg-agent.conf:

default-cache-ttl 28800
max-cache-ttl 86400

Then gpgconf --kill gpg-agent. Check "Save in Keychain" in the pinentry-mac dialog if you want macOS to hold it.


Back up your private key

If you lose it, you cannot re-sign anything with that identity, and revoking it is the only option.

gpg --export-secret-keys --armor "$KEYID" > gpg-private-backup.asc
gpg --gen-revoke "$KEYID" > gpg-revocation-cert.asc

Store both in a password manager or encrypted volume, never in a repo.


Alternative: SSH commit signing

If GPG is more ceremony than you want, Git 2.34+ can sign with the SSH key you already use for pushing:

git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true

Then add the same public key to GitHub a second time, under Settings → SSH and GPG keys → New SSH key, with key type set to Signing Key. No agent config, no pinentry, and it works identically across machines.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment