How to sign git commits from within an IDE like IntelliJ?
Question How do I sign git commits using an IDE like IntelliJ on Windows?
If you're interested, read what I tried here:
I followed mainly Github's guide. I made sure to not forget to restart bash/IntelliJ after you changed config files.
- Generate a new GPG key pair
- Add the GPG key to my GitHub account
-
Associate a verified (by GitHub) email with my GPG key where I made sure the email in my
.gitconfig
is the same. - Tell Git about my GPG key
- Sign a commit with GPG and confirmed that it was Verfied on Github.
- From that same page, I set commits to be signed by default with
git config --global commit.gpgsign true
(I'm using git 2.12). I made a new commit and verified it was signed withgit verify-commit HEAD
When I try to commit in IntelliJ, I get
gpg: cannot open tty 'no tty'
so I found IntelliJ fails to commit changes when attempting to sign commit (GPG) and addedno-tty
to myC:\Users\username\.gnupg\gpg.conf
file and restarted.Then I get the error
gpg: Sorry, no terminal at all requested - can't get input
which seems reasonable because I just added the option that has something to do with no terminal. Like gpg: Sorry, no terminal at all requested - can't get input says the solution is to remove theno-tty
which I hope doesn't apply to my case.Other answers in the first question suggested to add
use-agent
as well in thegpg.conf
file, which results in the additional errorgpg: gpg-agent is not available in this session
. Ah wait, maybe I need to setup gpg-agent.The best guide for Windows that I could find was the Archlinux wiki (yeah, right). It specifies to add to
C:/Users/username/.gnupg/gpg-agent.conf
the time to live, so I create that file and adddefault-cache-ttl 34560000
andmax-cache-ttl 34560000
as per https://superuser.com/questions/624343/keep-gnupg-credentials-cached-for-entire-user-sessionNow let's actually start this gpg-agent, https://superuser.com/questions/1153101/why-does-git-complain-that-no-gpg-agent-is-running made me check that indeed
gpg-agent --version
was much newer thangpg --version
, so I would like to have gpg2 so I could rungit config --global gpg.program gpg2
.But I do not have gpg2 available on the command line. I installed Gpg4win (binary releases, at the bottom) and even Gnupg 2 separately but that didn't give me gpg2 on the command line, I noticed I had to folder GNU in my Program Files (x86) which I think I should have. With
where gpg
I found out it was at least not pointing to the gpg I just downloaded, because that one showed second. So I pointed git to the right one withgit config --global gpg.program 'C:\Program Files (x86)\GnuPG\bin\gpg.exe'
Now I have the error
gpg: skipped "keyid": secret key not available
. The solution in gpg: skipped "N": secret key not available is what I just did, so that doesn't help. Then I realised I set everything up with the other gpg, not with this one. I didalias gpg="'C:\Program Files (x86)\GnuPG\bin\gpg.exe'"
, checkedgpg --version
and did the whole thing again. Actually I put the alias line in my.bash_profile
so I don't need to run it every time.When I try
gpg --gen-key
it hangs immediately. No idea why, I don't think the problem is not enough entropy because the older gpg worked fine but it's possible that the newer version requires more entropy. In any case I couldn't find any windows user with the same problem on the Internet.It works! When I commit in IntelliJ, it asks for my passphrase with pinentry only once. But now I can't commit from Git Bash, with the
no secret key
error which makes sense because as I saidgpg --list-keys
is empty: no key is associated with this gpg.Intellij IDEA signing GIT commits with GPG is relevant, but the only answer is for MAC and doesn't seem to apply to Windows. It did lead me to:
me.m01.eu hints at adding a new environment variable called
GNUPGHOME
which points toC:\Users\username\.gnupg
. That directory exists, but as mentioned in an answer from git commit signing failed: secret key not available I think my new gpg usesC:\Users\username\AppData\Roaming\gnupg
so I added that instead. I checked withprintenv GNUPGHOME
that I added it correctly (I had to reboot). Didn't change anything though.Since my keys are I think in
C:\Users\username\.gnupg
I tried pointing the environment variable to there, but it didn't help,gpg --list-keys
was still empty. So I had to find another way of pointing out to gpg where my keys are.gpg --list-keys --homedir='C:/Users/s156757/.gnupg'
did give the correct keys, so I decided to addhomedir C:\Users\s156757\.gnupg
to myC:\Users\username\AppData\Roaming\gnupg\gpg.conf
file which I had to create. Because of this bug. I confirmedgpg --list-keys
returned my keys. Still the same error, addingno-tty
anduse-agent
to this conf file didn't help.
I can now commit from within IntelliJ but not anymore with Git Bash, which results in
skipped "keyid": No secret key
.
More thoughts
- I didn't manage to export keys from gpg to gpg2 with
gpg --export [ID] | gpg2 --import && gpg --export-secret-keys [ID] | gpg2 --import
- I thought Gpg4win alone maybe could be configured so I don't need to type my password every time. Unfortunately, I couldn't find anywhere a way to make Gpg4win remember my passphrase.
- I later thought, if I remember correctly
gpg --list-secret-keys
has never returned anything for gpg 2. I only later found out that that command is different fromgpg --list-keys
.
In short this is the main problem: gpg-agent allows passphrase caching but the gpg version of git doesn't match the gpg-agent version so you have to install the right gpg 2 yourself first. But I didn't manage to do that installation in such a way that I could commit from both Git Bash and IntelliJ.
Solution 1:
Since git 2.19.1, gpg2 is supported!
gpg-agent can handle automatic signing now, remembering your passphrase
This should make it easier to use gpg to sign commits automatically. To be exact, git version 2.19.1 has at least gpg 2.2.9. These instructions were tested on Windows 7, Windows 8.1, Windows 10, Arch Linux and Fedora 29.
Steps to configure git commit signing
- It is recommended that you have set up ssh, see e.g. help.github.com/en/articles/connecting-to-github-with-ssh (also when you don't use GitHub)
- Start (on Linux) a terminal or (on Windows) git bash, check with
git --version
that git is at least 2.19.1 and withgpg --version
that you are using gpg2.
If not, check with where gpg
(or which gpg
if the where
command is not available) that the top-most path is the git one.
- If you see no paths or not any one which has gpg2, try the
gpg2
command instead ofgpg
, sogpg2 --version
. If that works, you'll have to usegpg2
instead ofgpg
from now on. - If you see a git path but it's not the top one, put (on Windows)
alias gpg="'C:\path\to\Git\usr\bin\gpg.exe'"
in yourC:\Users\username\.bash_profile
, create the file if it doesn't exist, and restart git bash. Trywhere gpg
andgpg --version
again. From now on, wheregpg
is typed into a file you should replace it with'C:\path\to\Git\usr\bin\gpg.exe'
.
- Check in the output of
gpg --version
if the home directory is something like (on Linux)/home/username/.gnupg
or (on windows)/c/Users/username/.gnupg
. This directory doesn't have to exist, yet.
If the path is incorrect, try to change it - for example one time on Windows I saw my home was prefixed by the path in which I ran the command, so I put an alias in the .bash_profile
with alias gpg="gpg --homedir=/c/Users/s156757/.gnupg"
and restarted bash, then checked again.
- The next few steps are from the good Github's guide, preferably you check there if commands are still correct. First, generate a new GPG key pair (but do not install the gnupg tools!): Run
gpg --full-generate-key
- Select RSA and RSA and 4096 bits.
- As real name use your
user.name
as in your~\.gitconfig
. - As email, use the email from
user.email
in your~\.gitconfig
, making sure that this email is a verified email on GitHub. - If you want to try gpg-agent (you will have to provide your password at least once after each reboot) or if you are fine with an 'unverified' badge on GitHub, provide a password. Otherwise, leave it empty.
- Every time your want to check what keys you have, use
gpg --list-secret-keys --keyid-format LONG
. Do it now, and copy thekey_id
(as I will name your key from now on) from the outputsec rsa4096/key_id 2018-10-27 [SC] ...
. - Print the public key with
gpg --armor --export key_id
. -
Add the GPG key to your GitHub account: go to
Settings | SSH and GPG keys
and add the public key block (including the header and footer). -
Tell Git about your GPG key in Settings > Version Control > Git > Configure GPG Key as shown in Mahozad's answer, please give it an upvote or tell git manually:
git config --global user.signingkey key_id
. - If you had to use the
--homedir
option before, you need to make sure that when git starts gpg, the home is also properly changed. Create a fileC:\Users\username\start-gpg.sh
and put into itgpg --homedir=/c/Users/s156757/.gnupg "$@"
. Then rungit config --global gpg.program C:\\Users\\username\\start-gpg.sh
to tell git to use it. - Restart bash.
-
Sign a commit with GPG with
git commit -S -m "signed commit"
and confirm that it is Verified on Github, you should see a little badge when you view your commit. - Set commits to be signed by default with
git config --global commit.gpgsign true
. Make a new commit in IntelliJ and verify if it was signed withgit verify-commit HEAD
.
Steps to make the commit signing happen automatically: three options
1. I have no passphrase on my key
You're done.
2. I want to try gpg-agent
For me this option didn't work: I still had to provide my passphrase often, though not always. But in theory this works:
- Update the cache time, in
C:\Users\username\.gnupg\gpg-agent.conf
: create file if it doesn't exist, adddefault-cache-ttl 34560000
andmax-cache-ttl 34560000
. - Restart gpg-agent using
gpgconf --kill gpg-agent
- Now you should have to enter your passphrase once when committing and then not anymore. Check that your commit is
Verified
on GitHub.
3. Pipe the passphrase in plaintext to gpg
This means that you never have to provide your passphrase, but for me this means that GitHub puts an Unverified
badge on my commit. Question here: The key whose key-id is in the signature did not sign this commit
- If you created it already, replace all of the contents of
C:\Users\username\start-gpg.sh
with the code below. If you didn't, create the file with the contents below, remove the--homedir
flag and rungit config --global gpg.program C:\\Users\\username\\start-gpg.sh
. In any case, restart bash.
Yes, you're going to place your password in plaintext on your computer! If you know a better way, please leave a comment...
# Passphrase-file-descriptor is set to 0 (STDIN), to use it --batch must be used
# The --pinentry-mode loopback is required since gpg 2.1.0 for --passphrase-fd
# The "$@" makes sure that whatever git wanted gpg to do, is still done
echo mypassphrase | gpg --homedir=/c/Users/username/.gnupg --passphrase-fd 0 --batch --yes --pinentry-mode loopback "$@"
- Commit and push and check that you were not asked for a passphrase, and that your commit is still
Verified
on GitHub.
Old answer for older git versions without gpg2
For the reference, here are the full instructions, or rather the steps I did to make it somewhat work. With 'work' I mean that commits are signed automatically, but there are two disadvantages:
- GitHub recognizes them as
unverified
:The key whose key-id is in the signature did not sign this commit. Someone may be trying to trick you.
The follow-up question regarding this is The key whose key-id is in the signature did not sign this commit - Creating a commit takes a much longer time, like five seconds instead of less than one.
If you get stuck, check the steps in the question to see if I had the same problem.
-
First few steps are from the good Github's guide: Generate a new GPG key pair
-
Add the GPG key to your GitHub account
-
Associate a verified (by GitHub) email with your GPG key and make sure the name and email in your
.gitconfig
are the same. -
Tell Git about your GPG key
-
Sign a commit with GPG and confirm that it is Verified on Github, you should see a little badge when you view your commit.
-
Set commits to be signed by default with
git config --global commit.gpgsign true
. Make a new commit and verify if it was signed withgit verify-commit HEAD
. -
The gpg version that comes with git is too old, so install Gpg4win (binary releases, at the bottom) which should install gpg 2. With
where gpg
you should see two path, of which probably the second is your new gpg, something likeC:\Program Files (x86)\GnuPG\bin\gpg.exe
. If not, try to install Gnupg 2 separately from the downloads page. -
I put
alias gpg="'C:\Program Files (x86)\GnuPG\bin\gpg.exe'"
to point thegpg
command to my new gpg in myC:\Users\username\.bash_profile
, restart Git Bash and check withgpg --version
that I'm now using gpg 2. -
Add a new environment variable called
GNUPGHOME
which points toC:\Users\username\.gnupg
. Reboot and check withprintenv GNUPGHOME
that you added it correctly. -
Make a script
C:\Users\username\gpg-no-tty.sh
and put into itecho passphrase | "C:\Program Files (x86)\GnuPG\bin\gpg.exe" --passphrase-fd 0 --batch --no-tty --yes "$@"
The reason you are putting your passphrase in plaintext here is because the --batch
option, which makes it all work, needs the passphrase fed. To me it seems like there should exist a better solution than saving your passphrase in plaintext on your computer, so please leave a comment if you found something better.
-
Point git to this script with
git config --global gpg.program C:\\Users\\username\\gpg-no-tty.sh
. -
Now test both in Git Bash and IntelliJ that you can commit, and verify that it worked by doing
git verify-commit HEAD
.
Solution 2:
IDEA is not a terminal and cannot handle signing at the moment. See https://youtrack.jetbrains.com/issue/IDEA-127802.
There is a workaround though, check the https://youtrack.jetbrains.com/issue/IDEA-127802#comment=27-1866498
Solution 3:
As of version 2021.2 of IntelliJ, you can configure the IDE to automatically sign the commits for you.
Refer to the IntelliJ documentations or the video tutorial for how to do this.
And refer to GitHub docs for how to add a GPG key to your GitHub account.