Signing and Verifying Git Commits on the Command Line and GitHub
We'll go over signing commits and tags with a GPG key along with sending and receiving GPG public keys to a Keyserver for verification.
There’s really no downside to signing your git commits and once you have a GPG key pair created you can auto-sign your commits and tags with a few git config options.
# Going Over Everything
Did you get a gpg failed to sign the data error while following along?
If you follow along you might encounter a “gpg failed to sign the data” error at 1:34 in the video if your configured git email and gpg key email are not the same. This will be addressed at 5:44 in the video when we explicitly configure git’s signing key.
It happened to work for me on video because in my case (and probably yours too), both email address values are the same. At the time of recording the video I wasn’t aware git’s signing key defaults to your configured git email.
Timestamps
- 0:46 – Creating a dummy git repo to work with
- 1:30 – Creating a signed git commit and verifying it
- 2:09 – Why it’s worth it to sign your commits
- 3:07 – Creating lightweight, annotated and signed git tags
- 5:15 – Auto-signing your commits and tags with a few
.gitconfig
options - 7:05 – Auto-signing tags requires git 2.23+ or newer
- 7:45 – Demonstrating auto-signing for commits and tags
- 8:41 – Adding your GPG public key to your GitHub account to get verified
- 10:44 – Verifying git commits from others on the command line
- 11:40 – Searching a GPG Keyserver for a specific user’s key
- 12:50 – Importing another user’s public GPG key straight from a Keyserver
- 14:24 – Deleting another user’s public GPG key from your keyring
- 15:10 – Sending your public GPG key to a Keyserver
- 16:21 – Importing another user’s GPG public key without a Keyserver
- 17:31 – Only merging in branches that have commits with verified signatures
- 19:26 – Recap and a quick tooltip for verifying signatures on GitHub directly
Reference Links
- https://nickjanetakis.com/blog/creating-and-managing-a-gpg-key-pair
- https://github.com/nickjj/dotfiles
# Cheatsheet
Here’s a reference to the commands run on video:
Unsigned commit
git commit -m "Unsigned commit"
git log
Signed commit
# If your git and gpg key email addresses are different this will fail until
# you configure your git signingkey (covered on video).
git commit -S -m "Signed commit"
git log --show-signature
Unsigned tag
git tag lightweight-tag
git show lightweight-tag
git tag -am "" unsigned-annotated-tag
git show unsigned-annotated-tag
Signed tag
git tag -sm "" signed-tag
git show signed-tag
Overriding the auto-sign config options
git commit --no-gpg-sign -m "Unsigned commit"
git tag --no-sign unsigned-lightweight-tag
Importing another user’s public GPG key from a Keyserver
As of mid 2021 the default gpg
key server was taken offline, there’s a few we
can choose as an alternative based on
https://en.wikipedia.org/wiki/Key_server_(cryptographic). I’ve been using
keyserver.ubuntu.com
as my new default. It’s updated pretty quickly and is
unlikely to go away.
We can either put --keyserver keyserver.ubuntu.com
in every command that
accesses the key server or we can modify our ~/.gnupg/gpg.conf
by searching
for the uncommented keyserver hkp://keys.gnupg.net
line and replacing it with
keyserver hkp://keyserver.ubuntu.com
.
I’ve gone with the config approach and recommend doing the same. This way all
of the commands below will continue to work without modifying them and you
don’t need to remember to use a custom server every time you use gpg
.
Changing the config file is effective immediately. You don’t need to restart the agent.
gpg --search-keys nick.janetakis@gmail.com
gpg --recv-keys D2AD01A3FC57C925
# Removing the key afterwards if you want to.
gpg --delete-keys nick.janetakis@gmail.com
Send your public GPG key to a Keyserver
gpg --list-keys --keyid-format LONG <your GPG email address>
gpg --send-keys <your public GPG key id from above>
This is useful to do if you want to exchange keys with someone and you should do this every time you change your key, such as updating its expiration date.
Importing another user’s public GPG key from a file
# Have them run this to export their public GPG key and send it to you.
gpg --export --armor --out theirname.gpg.pub <their GPG email address>
# Now you can import it like this.
gpg --import theirname.gpg.pub
Verifying signatures when merging a branch with git
# It's expected that you already modified your .gitconfig to auto-sign commits.
git checkout -b feaure-something
touch somefile && git add -A && git commit -m "Hello world"
git checkout master
git merge --verify-signatures feature-something
On GitHub you can also go-to a repo’s settings -> branches -> branch protection rules and add a rule to require signed commits on 1 or more branches. This way you can enforce this at the pull request level on GitHub.
Keep in mind if you do the above on GitHub then you may have less contributors because there is a barrier to entry to create a GPG key pair. Lots of larger projects do this. Personally I don’t impose this requirements on most of my open source projects, but I do sign all of my commits in either case.
Are you going to be signing your git commits? Let me know below.