Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Automatic Git commit signing with GPG on OSX
# In order for gpg to find gpg-agent, gpg-agent must be running, and there must be an env
# variable pointing GPG to the gpg-agent socket. This little script, which must be sourced
# in your shell's init script (ie, .bash_profile, .zshrc, whatever), will either start
# gpg-agent or set up the GPG_AGENT_INFO variable if it's already running.
# Add the following to your shell init to set up gpg-agent automatically for every shell
if [ -f ~/.gnupg/.gpg-agent-info ] && [ -n "$(pgrep gpg-agent)" ]; then
source ~/.gnupg/.gpg-agent-info
eval $(gpg-agent --daemon --write-env-file ~/.gnupg/.gpg-agent-info)
# Enables GPG to find gpg-agent
# Connects gpg-agent to the OSX keychain via the brew-installed
# pinentry program from GPGtools. This is the OSX 'magic sauce',
# allowing the gpg key's passphrase to be stored in the login
# keychain, enabling automatic key signing.
pinentry-program /usr/local/bin/pinentry-mac
# Uncomment within config (or add this line)
# This silences the "you need a passphrase" message once the passphrase handling is all set.
# Use at your own discretion - may prevent the successful interactive use of some operations.
# It is working fine for my use cases though.
# A quick outline of what must be done to get everything working.
# 1) Install the dependencies.
brew install gnupg gpg-agent pinentry-mac
# 2) Configure git to automatically gpgsign commits. This consists of
# pointing git to your signing key ID, and then enabling commit
# automatic signing.
git config --global user.signingkey <YOUR-SIGNING-KEY-PUB-ID>
git config --global commit.gpgsign true
# 3) Configure the GPG components (see above for relevant examples):
# ~/.gnupg/gpg.conf
# ~/.gnupg/gpg-agent.conf
# 4) Start the daemon and configure your shell (see above for example in .profile).
# ~/.bash_profile | ~/.zshrc
# Don't forget to upload your public key to Github!
# Note: There needs to be a three-way match on your email for Github to show
# the commit as 'verified': The commit email, github email, & the email associated with the public key
# Learn about creating a GPG key and the knowledge behind these commands here:

bmhatfield commented Apr 6, 2016

The high level "connection diagram" for each part:

git -> gpg -> shell/env variable -> gpg-agent -> pinentry -> keychain

Thanks for posting this! Two small suggestions/changes:

  1. I use Boxen, so Homebrew is installed in a different location. For ~/.gnupg/gpg-agent.conf I was able to use pinentry-program $HOMEBREW_ROOT/bin/pinentry-mac making the config more portable.
  2. I had to amend the gpg-agent command on startup: eval $(gpg-agent --daemon --options ~/.gnupg/gpg-agent.conf --write-env-file ~/.gnupg/.gpg-agent-info)

bcomnes commented Apr 6, 2016

Why do you use gpg instead of gpg2 or gnupg21? It comes with gpg-agent, pinentry as deps.

EDIT: My bad, pinentry-mac is does not come with the pinentry package.

bcomnes commented Apr 6, 2016

I came up with a slightly different recipe, using the latest version of gpg (2.1) and slightly less bash glue around the agent. Thanks for the writeup! It was helpful :)


bmhatfield commented Apr 7, 2016

@bcomnes - no particular reason on the gnupg choice. Just what I was used to. Thanks for sharing your workflow! Really the goal here is to highlight the pieces folks might need, so they can adapt them to their relevant approach.

rpereira commented Apr 8, 2016

@bmhatfield I've used this and it keeps me asking for the passphrase on every commit.


bmhatfield commented Apr 16, 2016

@ruiafonsopereira - sorry to hear that. The goal of this was more to try to give you all the pieces you needed to make this work, since it took me a little while to find them - you may have to adapt to your local environment. I wrote comments in each file with the intent of highlighting areas where you might do that. Some ideas I had to help troubleshoot: the .profile might not be sourced, or perhaps you didn't check "save in keychain" in the pinentry program, or perhaps gpg is installed in a way that it's looking for a different path, etc. Good luck!

Thank you!

lenage commented Aug 1, 2016

Thanks @danieleggert , it works like charm! 😄

I countered this error on your config:
"Inappropriate ioctl for device"
Write "export GPG_TTY=$(tty)" in ~/.profile and restart.


Thanks! This is fantastic.

aforty commented Dec 11, 2016

This is fantastic, thank you!

loustler commented Jan 26, 2017

Thanks guys.

I spent so many time to find solution for solve my problem.

Your solution is very fantastic.

Necmttn commented Mar 11, 2017


lumeng commented Mar 27, 2017

I was wondering that given that the gpg installed by Homebrew on macOS has switched to gpg2 which has some potentially important differences from gpg1, any of the above configuration can be updated and/or simplified?

abrkn commented Apr 26, 2017

Worked like a charm!

If you use gpg 2.1 or above, then cannot use --write-env-file.

See here

swernerx commented May 7, 2017

I think we don't even need to start gpg-agent anymore - at least not together with pinentry-mac ... works flawlessly without in my setup with gpg v2 (includes gpg-agent) + pinentry-mac (installed via homebrew).

@swernerx perhaps you could elaborate?

ewanmellor commented Aug 2, 2017

@jakeNiemiec Echoing the comment from @swernerx:

I have pinentry-mac 0.9.4 and gnupg / gpg-agent 2.1.22 from Homebrew, and I don't need to start gpg-agent manually; pinentry-mac does it for me the first time I try to sign something. This means that I do not need use-standard-socket in .gpg-agent.conf or the .profile changes above. Also, use-agent doesn't do anything any more (GPG Configuration Options).

All I needed was:

  • brew install gnupg gpg-agent pinentry-mac (same as above)
  • pinentry-program /usr/local/bin/pinentry-mac in ~/.gnupg/gpg-agent.conf
  • The git config commands above.

Amazing gist! ❤️

Quick tip for oh-my-zshell users:

Simply add gpg-agent to your plugins and skip the whole .profile part.

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