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.
.gitconfig
is the same.git config --global commit.gpgsign true
(I'm using git 2.12). I made a new commit and verified it was signed with git 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 added no-tty
to my C:\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 the no-tty
which I hope doesn't apply to my case.
Other answers in the first question suggested to add use-agent
as well in the gpg.conf
file, which results in the additional error gpg: 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 add default-cache-ttl 34560000
and max-cache-ttl 34560000
as per
https://superuser.com/questions/624343/keep-gnupg-credentials-cached-for-entire-user-session
Now 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 than gpg --version
, so I would like to have gpg2 so I could run git 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 with git 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 did alias gpg="'C:\Program Files (x86)\GnuPG\bin\gpg.exe'"
, checked gpg --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 said gpg --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 to C:\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 uses C:\Users\username\AppData\Roaming\gnupg
so I added that instead. I checked with printenv 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 add homedir C:\Users\s156757\.gnupg
to my C:\Users\username\AppData\Roaming\gnupg\gpg.conf
file which I had to create. Because of this bug. I confirmed gpg --list-keys
returned my keys. Still the same error, adding no-tty
and use-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
gpg --export [ID] | gpg2 --import &&
gpg --export-secret-keys [ID] | gpg2 --import
gpg --list-secret-keys
has never returned anything for gpg 2. I only later found out that that command is different from gpg --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.
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
Start (on Linux) a terminal or (on Windows) git bash, check with git --version
that git is at least 2.19.1 and with gpg --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.
gpg2
command instead of gpg
, so gpg2 --version
. If that works, you'll have to use gpg2
instead of gpg
from now on.alias gpg="'C:\path\to\Git\usr\bin\gpg.exe'"
in your C:\Users\username\.bash_profile
, create the file if it doesn't exist, and restart git bash. Try where gpg
and gpg --version
again. From now on, where gpg
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.
gpg --full-generate-key
user.name
as in your ~\.gitconfig
.user.email
in your ~\.gitconfig
, making sure that this email is a verified email on GitHub.gpg --list-secret-keys --keyid-format LONG
. Do it now, and copy the key_id
(as I will name your key from now on) from the output sec rsa4096/key_id 2018-10-27 [SC] ...
.gpg --armor --export key_id
.Settings | SSH and GPG keys
and add the public key block (including the header and footer).git config --global user.signingkey key_id
.--homedir
option before, you need to make sure that when git starts gpg, the home is also properly changed. Create a file C:\Users\username\start-gpg.sh
and put into it gpg --homedir=/c/Users/s156757/.gnupg "$@"
. Then run git config --global gpg.program C:\\Users\\username\\start-gpg.sh
to tell git to use it.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. git config --global commit.gpgsign true
. Make a new commit and verify if it was signed with git verify-commit HEAD
.You're done.
For me this option didn't work: I still had to provide my passphrase often, though not always. But in theory this works:
C:\Users\username\.gnupg\gpg-agent.conf
: create file if it doesn't exist, add default-cache-ttl 34560000
and max-cache-ttl 34560000
.gpgconf --kill gpg-agent
Verified
on GitHub.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
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 run git 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 "$@"
Verified
on GitHub. 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:
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 commitIf you get stuck, check the steps in the question to see if I had the same problem.
.gitconfig
are the same.Set commits to be signed by default with git config --global commit.gpgsign true
. Make a new commit and verify if it was signed with git 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 like C:\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 the gpg
command to my new gpg in my C:\Users\username\.bash_profile
, restart Git Bash and check with gpg --version
that I'm now using gpg 2.
Add a new environment variable called GNUPGHOME
which points to C:\Users\username\.gnupg
. Reboot and check with printenv GNUPGHOME
that you added it correctly.
Make a script C:\Users\username\gpg-no-tty.sh
and put into it echo 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
.