Today I’ve decided to improve my Github account settings a bit. I thought that it would be nice to add GPG key to it and sign all commits pushed from my computer. Everything worked great until I tried to commit the first change directly from my IntelliJ IDEA.

Introduction

Why even bother with signing commits with GPG key? The most important reason is quite simple - it proves that you are the author of a given commit. Or to be more precise - the key that was used to sign this commit matches the key associated with your account. Github honors signing commits with this pretty lovely badge added to the commit history log.

github gpg signing

Signing git commits make even more sense if you use tools like Keybase.io to chat and share files in a secure (encrypted) fashion.

How to sign Git commits?

First of all, you need to have a GPG key. Github’s help page[1] explains in details how to generate a key, as well as how to associate it with your account. I encourage you to read it - it won’t take more than 5 minutes of your time.

Next, you need to configure your Git client to use the key. Depending on your preferences, you might want to set up GPG signing globally, or you can do it locally for a single repository. In my case, I decided to set up signing commits at the global level with the following two commands:

$ git config --global commit.gpgsign true
$ git config --global user.signingkey YOURKEYHERE

If you use Git from the command line, that is all you have to do. You can create the first commit and push it to Github to see "Verified" badge next to your commit history log entry.

Getting into troubles with IntelliJ IDEA

I assume you also use your IDE’s built-in Git client. I use IntelliJ IDEA daily, and I use its Git client a lot. When I tried to create the first commit after enabling GPG signing, IDEA’s client stopped working, and it started failing with the following error:

gpg failed to sign the data fatal: failed to write commit object

I started googling to see what the problem is. It quickly turned out that this is not the IDEA’s problem, but rather Git and GnuPG issue. It fails to sign the commit if Git command is executed without TTY, so GPG cannot prompt to ask you for a password. I’ve quickly found a solution that suggested creating an alias that executes gpg with --batch --no-tty options. I created a script:

Listing 1. /usr/local/bin/gpg-no-tty
#!/bin/bash
/usr/bin/gpg --batch --no-tty "[email protected]"

Then I added the following block to my .gitconfig file.

Listing 2. .gitconfig
[gpg]
program = gpg-no-tty

The solutions I’ve found promised that in this case IDEA will use gpg-agent that can store the password in the keyring and automatically sign the commit. Well, it didn’t work for me. At least not right away.

Fedora Linux 29 use case

I use Fedora Linux, and it seemed to be a critical factor in this story. I had to went through a few more articles, and I’ve finally found the answer. When I applied the solution that uses --batch --no-tty for the first time, it didn’t take any effect. However, it turned out that gpg-agent works with GPG 2.x. When I run gpg --version I noticed the following:

$ gpg --version
gpg (GnuPG) 1.4.23
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: ~/.gnupg
Obsługiwane algorytmy:
Asymetryczne: RSA, RSA-E, RSA-S, ELG-E, DSA
Symetryczne: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256,
             TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256
Skrótów: MD5, SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Kompresji: Nieskompresowany, ZIP, ZLIB, BZIP2

It revealed that gpg in my system points to version 1.4.23. Would it mean that there is no GPG 2.x in Fedora Linux? Nope, not really. GPG 2.x is available for Fedora Linux, but as a gpg2 shell command.

$ gpg2 --version
gpg (GnuPG) 2.2.13
libgcrypt 1.8.4
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /home/wololock/.gnupg
Obsługiwane algorytmy:
Asymetryczne: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Symetryczne: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256,
             TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256
Skrótów: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Kompresji: Nieskompresowany, ZIP, ZLIB, BZIP2

When I replaced the initial script with gpg2 - it worked as expected.

Listing 3. The final version of /usr/local/bin/gpg-no-tty
#!/bin/bash
/usr/bin/gpg2 --batch --no-tty "[email protected]"

I was able to create the first commit from IntelliJ IDEA. The gpg-agent prompted for the password and I was able to store it in the keyring.

github gpg idea

UPDATE: --batch --no-tty not needed with GPG2

I just make some experiments and it seems like using intermediate script that adds --batch --no-tty switches is no needed when you use gpg2 with gpg-agent. (At least in my case). My current setup is the following. I have changed the default gpg program to gpg2 in my ~/.gitconfig file:

Listing 4. Make sure the following two lines are added at the end of your `~/.gitconfig file
[gpg]
program = gpg2

Here is my gpg-agent version.

$ gpg-agent --version
gpg-agent (GnuPG) 2.2.13
libgcrypt 1.8.4
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Make sure that gpg-agent daemon is running. You can start it with the following command:

$ gpg-agent --daemon

When you create a first signed commit via command line or from IntelliJ IDEA (I’ve checked both cases after removing remembered password from the keyring), gpg-agent will prompt and ask you for a password that can be stored in the keyring.

github gpg idea

If you removed remembered GPG key password from the keyring and you want to test if gpg-agent prompts again for the password correctly, remember to shut down the daemon and restart it.

$ gpgconf --kill gpg-agent

$ gpg-agent --daemon

Conclusion

If you are interested in enabling GPG signing of your Git commits, consider checking this step-by-step guide, where you can find even more information about the setup process. Happy hacking!

Szymon Stepniak

Groovista, Upwork's Top Rated freelancer, Toruń Java User Group founder, open source contributor, Stack Overflow addict, bedroom guitar player. I walk through e.printStackTrace() so you don't have to.