Skip to content

Instantly share code, notes, and snippets.

@vegadodo
Created November 26, 2020 05:46
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vegadodo/a685134a53b067b4b15c279d2b93036f to your computer and use it in GitHub Desktop.
Save vegadodo/a685134a53b067b4b15c279d2b93036f to your computer and use it in GitHub Desktop.
How to sign existing commits and tags, starting from certain commit (for PRIVATE repo)

How to sign existing commits and tags, starting from certain commit (for PRIVATE repo)

Author

Vegadodo (@vegadodo)

DISCLAIMER

This might seriously fuck up repo history, so use at your own risk. Also, this might have some unintended side effects. Probably use for your PRIVATE repo only!

What does this do

  • Sign exisiting commits and tags, starting from certain commit.
  • Will retain commit dates and messages.
  • Will retain tags, what commits tags refer to, and tag date.
  • This is a kind of makeshift method. Several things can be improved (hopefully).

Why did I make this gist

  • Because one of my commits from a week ago had a bad signature.
  • That rogue commit was Unverified, and it being there among other beautiful Verified commits was such a pain for me.
  • So I needed to sign commits and tags again, starting from that rogue commit.
  • Also, since several tags were refering to soon-to-be update commits, I needed to make new commits to refer to updated commits, too.
  • After several hours of googling and gathering pieces of info, I finally found how to do that job.

What can be improved

  1. Make this a zsh script.
  2. More safe backup method in STEP 0.
  3. Use git-filter-repo instead of git-filter-branch in STEP 1 (might not be possible).
  4. Automate stuffs in STEP 2.
  5. Maybe use branching as a failsafe in STEP 1.

STEP 0: Before starting, backup your current repo

In my case, since my changes were already pushed to remote, I just wiped and cloned the repo again.

rm -rfv <REPO_NAME>
gh repo clone <GITHUB_USERNAME>/<REPO_NAME>
cd <REPO_NAME>

STEP 1: Sign previous commits and update tags to point new commits

Sources

# If you want to sign commits and tags from the beginning of the repo, use
# git filter-branch --tag-name-filter cat --commit-filter 'git commit-tree -S "$@";' -- --all

git filter-branch --tag-name-filter cat --commit-filter 'git commit-tree -S "$@";' <ID_OF_COMMIT_BEFORE_FIX>..HEAD

STEP 2: Sign updated tags again

As far as I know, filter-branch will strip signature in tags. Therefore, you have to sign your tags again.

Sources

# I did not figure out how to automate this process.
# Since I only had 6 tags to sign again, I just did this step manually.
# For the large number of tags to be signed again, I guess automation is necessary.

# Repeat for every updated tags.
GIT_COMMITTER_DATE="$(git log -1 --format=%aD <UPDATED_TAG_NAME>)" git tag <UPDATED_TAG_NAME> <UPDATED_TAG_NAME>^{} -f -s -m "<TAG_MESSAGE>"

STEP 3: Push updated commits and tags to remote

git push -f
git push -f --tags

That's it! Now all your commits and tags are properly GPG signed, and you get to enjoy your Verified commits and tags in your GitHub repo page.

@davevelasco
Copy link

Thank you for this gist! I had an additional issue on my part where my old unsigned commit used a different commit email to my gpg key email. I modified step 1 by adding --env-filter 'GIT_AUTHOR_EMAIL=<EMAIL>; GIT_COMMITTER_EMAIL=<EMAIL>;' which did the trick.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment