Can you GPG sign old commits?
Emily Wong
Git now has the ability to sign commits with git commit -S, which is great, but sometimes I forget the flag to commit, and sometimes I mail myself patches which I apply with am, and that command doesn't have a flag for signing.
Is there a way to add a signature to an already recorded commit?
39 Answers
- Go into interactive rebase mode.
Add the following line after each commit you want to sign
exec git commit --amend --no-edit -S
This will run this command after picking each commit.
UPDATE:
Easier way to do this is:
git rebase --exec 'git commit --amend --no-edit -n -S' -i developmentThis rebases everything till development (or any hash) and you don't have to copy paste after every commit.
11Signing a commit changes its contents, so more recent commits depending on it will change their hash.
If you just want to sign the most recent commit, git commit -S --amend will work.
I use git rebase -i --root ( see Rewriting History ) and change pick to edit.
Then I use git commit -S --amend --no-edit && git rebase --continue (on Windows) for each commits.
2This is manually sign for each commits. I hope we will found better solution.
If you need to GPG sign all commits SINCE a particular commit on the current branch, you can use the following instead:
git filter-branch --commit-filter 'git commit-tree -S "$@";' <COMMIT>..HEADWhere <COMMIT> is the commit id (e.g. abc123e5).
This has the added benefit that it does not disturb the commit metadata (including commit date). The commit hashes will change, though (since it's a digest of the contents of each commit, and a signature is being added to each commit).
If you also would like to stop getting prompted for your GPG passphrase on every commit, also see this answer:
NOTE: Switching from gpg to gpg2 for GIT signing will require you to re-import your private key in GPG 2.
If you want to filter only specific commits and sign only them you can use filter-branch:
git filter-branch --commit-filter 'if [ "$GIT_COMMITTER_EMAIL" = "" ]; then git commit-tree -S "$@"; else git commit-tree "$@"; fi' HEADThis is useful if, for some reason, you want to sign only your own commits.
I also stumbled on the same problem and here is my solution:
git rebase -i --root --exec 'git commit --amend --no-edit --no-verify -S'this will sign all of my commits from the first initial commit and also bypass commit hook that I set up using husky. No need to change pick to edit.
If no filtering on commit is needed, then it is preferred to use rebase than filter-branch:
git rebase -i master --exec 'git commit --amend --no-edit --no-verify -S --reset-author'Else, you can leave untouched the commits you don't own.
Set the following alias in ~/.gitconfig (replace with your email address):
resign = "!_() { : git checkout ; [ \"$#\" -eq 0 ] && echo 'Usage: resign <rev-list>' && exit 2; \ git filter-branch --commit-filter ' \ if [ \"$GIT_COMMITTER_EMAIL\" = \"\" ]; then git commit-tree -S \"$@\"; else git commit-tree \"$@\"; fi' $1; }; _"Then for instance, to resign all your commits in the current branch pulled from master, do:
git resign master..Credits to previous answers byBarryMode and Roberto Leinardi
To sign off last N commits, you can also do:
git rebase HEAD~N --signoff 3 here's the one I use for all commits, yes it will re-write history:
git rebase --exec 'git commit --amend --no-edit -n -S' -i --root 1