Oops, I forgot to sign my commit from last Monday...
Updated: February 22, 2022 12:15
Published: January 28, 2020 13:44
How to interactively use git rebase to fix unsigned GPG commits.
This is mainly a "post-it note to self" as I usually don't forget to sign my git commits, but occasionally I run into issues where I don't notice a commit has not been signed until 30 commits later. Here's the solution...
TL;DR
- 1)
git rebase -i ID_OF_COMMIT_BEFORE_FIX
- 2) change
pick
toedit
for the commit(s) needing a GPG signature and save. - 3)
git commit --amend --no-edit -S
- 4)
git rebase --continue
The Backstory
In my usual workflow, especially when working with software that utilizes Git Flow like branches, I use GitKraken for visualization of the git structure. It has a nice UI and does a great job at presenting git repositories. But it does lack some "advanced" features to be truly useful to me. Such as handling complex GPG / SSH key setup's. (More on that in a future post)
This morning I was working on [geeshoe/atom](https://github.com/geeshoe/atom), a PHP library to to generate fully compliant RFC4287 RSS/Atom feeds (Currently in initial development). I had mistakenly performed a cherry pick using GitKraken. I say mistakenly because as I mentioned previously, GitKraken doesn't recognize my GPG key setup, so while it did perform the cherry pick, GitKraken didn't actually sign the commit. I didn't notice this until after I had pushed a PR up to GitHub and seen one of my commits didn't have the green "verified" tag. Dang it!
Are my commits signed?
In the CLI, git log --show-signature
let's you know...
I've modified the output above for readability but as you can see, the first (Initial commit) & the third (updated doc) commits were both signed using my GPG key. The second commit (ignore ideas) however was not signed.
The fix
As the above scenario doesn't happen often to me, I always seem to forget how to sign previous commits without getting into a git mess. After doing some googling, rebasing hit's me square in the forehead. Duh!
The key is that we want to begin the rebase at the commit just before
the commit which needs to be modified. In this case it will be the
initial commit c772d80
. We also want to rebase interactively.
git rebase -i c772d80
will open a text editor that
will allow use to tell git which commit we want to modify.
We are going to change pick
to edit
for
pick 95f8587 ignore ideas
within the editor and save as shown below.
Git will then bring you back to the command prompt and halt at the commit that needs editing:
Now we can sign the commit using git commit --amend --no-edit -S
--amend
Amend the previous commit. --no-edit
Use the existing commit message. No need to edit it.-S
GPG-sign the commit. If you need to specify the GPG key to use,
-S[
is more appropriate.
After running the above command, git will output something similar to the following:
We can now go ahead and finish up the rebase with git rebase --continue
& if all goes well, git will tell you that the rebase was successful. To
verify that we signed the commit, git log --show-signature
should now show the GPG signature:
You're all set! Happy coding...
But, A word to the wise...
If you have already pushed the unsigned commit upstream to github as I did, care should be taken before using the above described method. As there could be negative consequences.
First, after performing the rebase, you will more than likely have to force push the branch upstream to github. If this is a feature branch that hasn't been merged / modified by others, forcing the push shouldn't cause any headaches.
If there have been modifications to the branch / PR upstream, you may want to revert the commit, and just create a new signed commit rather than doing a rebase. If all else fails, you can always let the unsigned commit ride solo as a reminder not to make that mistake again...
As always comments, rants, suggestions, and constructive criticism are always welcome.
- Jesse Rushlow[email protected]