the avatar image of Benjamin Bouvier

TIL: automatically signing Git commits and adding signoffs

For a new work project, I had to set up GPG signing and add the signed-off-with trailer to all my commit messages. I’m using lazygit, so while these options are available in the command line, I needed some more general way to do this. Here’s how I’ve done it, in case it’s useful to other folks.

🔗What is signing?

Signing is committing a proof that you are who you claim you are, and/or that you are the one who did what you did. In some ways, it is the reciprocal operation of encrypting: signing (=~ “encrypting”) some public content makes use of your private key, so that people on the other end can check the signature (=~ “decrypt”) with the public key, and assert that the decrypted content is what they see too.

🔗Setting up GPG

These commands have been tested against gpg version 2.4.9.

Create a new key:

gpg --full-generate-key

Show a list of your known keys:

gpg -k

Note the long ID for your key (a string of random letters and numbers), then export it:

gpg --armor --export LONG_ID

This can then be copied into your Github/Gitlab settings, in the GPG key section.

🔗Verify commits with GPG signing

You can decide to commit and sign individual commits:

git commit -S

Then, you can check that a commit has been signed by looking at the log; it’s not displayed by default:

git log --show-signature

…Or request to always commit and sign with a GPG key, which can be handy if you’re using nice external tools wrapping git like lazygit:

Within the context of one git repository:

git config commit.gpgsign true
git config user.signingkey LONG_ID

Or if you want to do it for all your projects, add --global to these commands.

🔗Bonus: always add Signed-off-with mention to your commits

You can do it on a per-commit basis as well [1]:

git commit -s

Use the following git hook, by writing a new file in ${PROJECT}/.git/hooks/prepare-commit-msg:

#!/bin/sh

NAME=$(git config user.name)
EMAIL=$(git config user.email)

if [ -z "$NAME" ]; then
    echo "empty git config user.name"
    exit 1
fi

if [ -z "$EMAIL" ]; then
    echo "empty git config user.email"
    exit 1
fi

git interpret-trailers --if-exists doNothing --trailer \
    "Signed-off-by: $NAME <$EMAIL>" \
    --in-place "$1"

Make sure the git hook is executable with:

chmod +x ${PROJECT}/.git/hooks/prepare-commit-msg

Courtesy of this StackOverflow answer.

  1. Yay for the options being -s for adding the signed-off-with mention in the commit message, and -S for signing with GPG. Ergonomics, amirite?