Signing Commits with IntelliJ IDEA Editors (like PyCharm)

Verified Commit Signature on GitLab

Want to prove that you actually committed the code attributed to your name in git repositories (and get that nice Verified stamp on your commit on GitHub or GitLab)? So did I. I followed the instructions on GitHub (which are remarkably similar to those on GitLab) but found that my commits using PyCharm still didn’t include the signature. Here’s how to get it working.

Create your key

Install GPG

  • Create your key
gpg --full-gen-key
  • You’ll be asked some questions; answer as you see appropriate. Choose RSA and RSA, and use 4096 bits (this is also recommended by GitLab). I also like to set an expiry on my keys – I set this to 2 years below. Note that your email address must match an email address verified on your GitHub / GitLab account(s).
Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
<...>
Key is valid for? (0) 1y
Key expires at Mon 27 Jul 2020 05:38:19 PM EDT
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: Peaks And Protocols
Email address: peaksandprotocols@example.com
Comment: This is an example key
You selected this USER-ID:
    "Peaks And Protocols (This is an example key) <peaksandprotocols@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o

<...>

gpg: key 990B8E9D86ED660F marked as ultimately trusted
gpg: revocation certificate stored as '/home/jrokeach/.gnupg/openpgp-revocs.d/1C0476B1F7659A7F063F6637990B8E9D86ED660F.rev'
public and secret key created and signed.

pub   rsa4096 2019-07-28 [SC] [expires: 2020-07-27]
      1C0476B1F7659A7F063F6637990B8E9D86ED660F
uid                      Peaks And Protocols (This is an example key) <peaksandprotocols@example.com>
sub   rsa4096 2019-07-28 [E] [expires: 2020-07-27]
  • Grab your key ID from the line below pub; in the above example, it’s 1C0476B1F7659A7F063F6637990B8E9D86ED660F. Use this for <keyid> and execute gpg --armor --export <keyid>
$ gpg --armor --export 1C0476B1F7659A7F063F6637990B8E9D86ED660F
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQINBF0+FfwBEACzb3Phra1NAEPWObG4aUz9v3zebOJI9qDP1sD4G3HlyDRfh4Tn
acSxIZHtQV8vLtDl+vmjj4PxW3NLZJCZmbLWIbikmVjZDMSxsfnVxTEUxF8itvk1
<truncated>uH4p2BUQNBF/gunvxyQVXjrA+JC4fc/zuvvrJ12MQL6qCs2GuiwnB
g0MHLAz4TkSHR7nt7bC8LP6bovl8FP14FN6xlXusbAQ0ckHB+OcMYH9GjH7WhgHo
-----END PGP PUBLIC KEY BLOCK-----
  • Copy the full exported public key, including the -----BEGIN PGP PUBLIC KEY BLOCK----- and -----END PGP PUBLIC KEY BLOCK----- lines, and paste them into as a new GPG key on GitHub and/or GitLab as appropriate.

Tell Git to sign your commits

Now that you have a key, and you’ve associated it with yourself on GitHub/GitLab, you’ll need to tell Git to actually sign your commits.

  • Get your key ID by running gpg --list-secret-keys --keyid-format LONG <your_email>. In the following example, the key ID is 990B8E9D86ED660F.
$ gpg --list-secret-keys --keyid-format LONG peaksandprotocols@example.com
sec   rsa4096/990B8E9D86ED660F 2019-07-28 [SC] [expires: 2020-07-27]
      1C0476B1F7659A7F063F6637990B8E9D86ED660F
uid                 [ultimate] Peaks And Protocols (This is an example key) <peaksandprotocols@example.com>
ssb   rsa4096/0ABF70532FBB4582 2019-07-28 [E] [expires: 2020-07-27]
  • Tell git to use your key globally. Run git config --global user.signingkey <Key ID>
  • Optionally, tell git to use your key for a single repository. Within the directory of your git project, run git config --global user.signingkey <Key ID>. I use this to sign different projects with my personal and work email addresses.
  • Now, tell git to always sign your commits: git config --global commit.gpgsign true. Of course, you could also tell git to sign each commit individually,

Make key signing work without TTY

So, we’ve gotten far enough that we can sign commits, but PyCharm or other similar apps won’t work yet. There’s some great discussion on StackOverflow that led me to this solution.

  • Create a new file named gpg-no-tty.sh with the contents (replacing </path/to/gpg>, of course:
    echo passphrase | "</path/to/gpg>" --passphrase-fd 0 --batch --no-tty --yes "$@"
  • Tell git to always use this file to execute gpg (replacing </path/to/gpg-no-tty.sh>:
    git config --global gpg.program </path/to/gpg-no-tty.sh>

Now try out a commit in your IDE, and you should see it works! You can verify with git log -n 1 --show-signature, or just view it once you push to GitHub/GitLab.

Leave a Reply