Signed Git commits allows us to be sure that a commit has been made by the user (name and email) that the git log says.
To do so we’ll use a GPG key.
Generate a GPG key
First we need to install GPG:
brew install gnupg
Once it’s installed we’ll create the key:
We’ll select RSA and RSA kind of key:
Please select what kind of key you want: (1) RSA and RSA (2) DSA and Elgamal (3) DSA (sign only) (4) RSA (sign only) (9) ECC (sign and encrypt) *default* (10) ECC (sign only) (14) Existing key from card Your selection? 1
Then, we’ll chose
RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (3072) 4096 Requested keysize is 4096 bits
We’ll also chose to not expire:
Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) Key does not expire at all Is this correct? (y/N) y
After getting a verification step to ensure that everything is ok we’ll be asked for a password that will be requested every time we do a Git commit.
We’ll need to get the GPG key ID:
gpg --list-secret-keys --keyid-format LONG <your_email>
The output will be:
gpg: checking the trustdb gpg: marginals needed: 3 completes needed: 1 trust model: pgp gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u sec rsa4096/DDDDAAAA11113333 2021-05-12 [SC] 1111792333392BE6F4431E32DA917BCEB3666622 uid [ultimate] Your Name <email@example.com> ssb rsa4096/1234BF57VVVV3333 2021-05-12 [E]
We need the sec ID:
With it we can then run this command to get the public key block:
gpg --armor --export DDDDAAAA11113333
Use this public key to configure your GitLab or GitHub account. You’ll find a place to add GPG keys in your user preferences.
Then we also need to setup our computer to be able to use that key:
git config --global user.signingkey DDDDAAAA11113333 git config --global gpg.program gpg
Add the following text to
~/.gnupg/gpg.conf. Create the file if doesn’t exist:
GPG_TTY environment variable in your
Then if we want to just sign the commits sometimes we can just add
-S parameter when doing a
git commit -S -m "Test"
But if we want we can set up Git to do it always:
git config --global commit.gpgsign true
If you get the following error:
gpg: signing failed: Inappropriate ioctl for device gpg: [stdin]: clear-sign failed: Inappropriate ioctl for device
GPG_TTY is well exported. Maybe you are missing a
source ~/.zshrc call.
If you get the following error when doing commits:
error: gpg failed to sign the data fatal: failed to write commit object
To troubleshoot try first to execute:
echo "test" | gpg --clearsign, you might get something like:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 test gpg: signing failed: No pinentry gpg: [stdin]: clear-sign failed: No pinentry
If you get that you either need to install
brew install pinentry
or kill gpg agent after upgrading it:
gpgconf --kill gpg-agent