Signed Commits

How to get the shiny “Verified” badge on GitHub.

Izaak Schroeder
Nov 6, 2018 · 5 min read

Also known as: “the four easy steps to stopping people from doing fun things like this”:

git commit -am "Destroy production"
git filter-branch --env-filter \
'if [ "$GIT_AUTHOR_EMAIL" = "me@evilguy.com" ]; then
GIT_AUTHOR_EMAIL="unsuspectingvictim@mywork.com";
GIT_AUTHOR_NAME="Unsuspecting Victim";
GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL;
GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; fi' -- --all
git push -f

Signing all your commits with a private key only you hold means other less well-intentioned individuals cannot forge commits on your behalf. This key is different from your SSH keys which only exists to authenticate your identity to GitHub (or other SSH-based origins), not to authenticate the authorship of the commits themselves.

Step 1: Install GPG

brew install gnupg pinentry-macmkdir -p "$HOME/.gnupg"
chmod 700 "$HOME/.gnupg"
echo "no-greeting" >> "$HOME/.gnupg/gpg.conf"
echo "use-agent" >> "$HOME/.gnupg/gpg.conf"
echo "use-standard-socket" >> "$HOME/.gnupg/gpg-agent.conf"
echo "pinentry-program /usr/local/bin/pinentry-mac" >> "$HOME/.gnupg/gpg-agent.conf"

NOTE: This assumes a typical homebrew installation; if you have custom settings adjust the /usr/local/bin/pinentry-mac path accordingly. You can find this path by running which pinentry-mac.

Step 2: Create a GPG Key

gpg --gen-key

IMPORTANT: The name and e-mail you use must match the name and e-mail you configured in git. You can see the values you’ve configured by running the command: git config --global --get-regexp user..

If you’ve configured everything properly you should be prompted for a password to use with your new key:

NOTE: If you get an error complaining about a missing pinentry program then most likely you just need to restart gpg-agent. You can open “Activity Monitor”, search for gpg-agent, kill it and re-run the commands.

After generating your key, it should print out some information you will need to use in the following steps. The bolded value below will henceforth be referred to as HEXKEYGOESHERE.

pub   rsa2048 2018-04-23 [SC] [expires: 2020-04-22]
08EF873ADD30E043E17FA6B931B825A7737BA24
uid Sir Izaak <izaak@metalab.co>
sub rsa2048 2018-04-23 [E] [expires: 2020-04-22]

Remember to store your key somewhere safe. This will typically be your password manager like 1Password. Remember these are personal identity keys and not machine identity keys, so it is desirable to have them backed up.

gpg --export-secret-keys HEXKEYGOESHERE > backup.gpg

Step 3: Configure Git

git config --global user.signingkey HEXKEYGOESHERE
git config --global commit.gpgsign true

You can verify this is working by attempting to commit anything and then viewing the log with signatures turned on:

mkdir ~/test
cd ~/test
git init
echo "test" >> test
git add test
git commit -m "test"
git log --show-signature

You should see something that looks like:

commit ... (HEAD -> ...)
gpg: Signature made Mon 16 Apr 03:33:15 2018 PDT
gpg: using RSA key HEXKEYGOESHERE
gpg: Good signature from "Sir Izaak <izaak@metalab.co>" [ultimate]

Step 4: Configure GitHub

gpg --armor --export HEXKEYGOESHERE

Paste everything into the following form:

If you’ve done it all right you should see commits on GitHub that look something like this:

And then simply make sure master (and any other non-feature branches) only allows signed commits.

In The End

Sign your commits. Get the shiny badge. 🙏

‡ Troubleshooting

Error: “signing failed: No secret key”

GitHub GPG Key E-Mail “Not Verified”

And all you need to do to fix it is go into the e-mail settings in your GitHub account and add the e-mail you’ve chosen. This will also fix missing profile photos and links where GitHub displays commits.

Bootstart

This will go.