As the title says, I'm looking for a way to gpg sign all my previous commits in a repository (preferably without typing in my passcode for every commit).
-
1Here's [an old superuser post](http://superuser.com/questions/397149/can-you-gpg-sign-old-commits) which has a few answers to this question. – PatrickSteele Jan 26 '17 at 21:11
-
Is there any way to do this automatically using `filter-branch` or something like that? Those solutions require me to go and mess with things in an interactive rebase. – pradyuman Jan 26 '17 at 21:17
-
4A commit depends on all previous commits. So if you sign one commit, you are implicitly signing all the history that led up to that commit. – G. Sliepen Jan 26 '17 at 21:27
-
2I'm agreeing with @G.Sliepen here, but I would also add that there are theoretical approaches to breaking SHA-1 that *might*, under some as-yet-improbable scenarios, allow an attacker to replace some intermediate history commit and thereby foil the Merkle hash chain guarantee that signing a later commit implicitly covers all the earlier commits. In other words, GPG-signing *each* commit is in theory more secure today. In practice it's not really worth worrying about. – torek Jan 26 '17 at 22:29
-
Does this answer your question? [Signing an existing commit with GPG](https://stackoverflow.com/questions/37737096/signing-an-existing-commit-with-gpg) – chalasr May 05 '22 at 23:05
-
See also answers in superuser discussion [Can you GPG sign old commits?](https://superuser.com/questions/397149/can-you-gpg-sign-old-commits) – Michael Freidgeim May 08 '22 at 01:44
4 Answers
My approach is
git rebase --exec "git commit --amend --no-edit -n -S" -i 8fd7b22
All commits started from the next after 8fd7b22
will be rebased with no changes except signing. To change all commits started from the very first one you may use --root
(since Git v1.7.12):
git rebase --exec "git commit --amend --no-edit -n -S" -i --root
To spread changes to the remote I use
git push --force
Note, this will update "gpg made" date-time and, for example, GitHub will treat it as commit date. Git itself persists both original and new dates, git log --show-signature
gives clear picture of when the original commit was made and when it was signed for the last time.

- 18,707
- 8
- 70
- 85
-
4While this works, I'd like to add that this destroys the actual commit date. @dhilt, you should've considered adding that in the answer as well. So, not "no changes" except signing. – roshnet Aug 03 '20 at 18:50
-
@roshnet I did little research and updated the answer. If you have anything more, I'd be happy to dig deeper. – dhilt Aug 04 '20 at 00:13
-
-
How can I sign the very first commit? I signed all commits after the first, but don't know how to sign the initial commit. – sansari Nov 19 '20 at 15:05
-
@sansari Good question! I updated the answer to provide solution (--root). – dhilt Nov 20 '20 at 15:35
-
@dhilt adding root would pull entire history, not only the current branch – sansari Nov 20 '20 at 19:23
-
1@sansari use `--root [
]` syntax to specify the branch, reffer to [git-rebase doc](https://git-scm.com/docs/git-rebase) – dhilt Nov 21 '20 at 16:58 -
I would like to add that this method destroys the commit tree, and instead commits will be committed consecutively (in graph terminology, it becomes a path). So if you like me would like to preserve your commit-graph, use the accepted answer. – Aria Mar 27 '22 at 19:36
-
1On Windows shell(e.g. cmder) you may need to change single quotes to double quotes. `git rebase --exec "git commit --amend --no-edit -n -S"` -i 8fd7b22 See https://superuser.com/questions/1656806/why-git-commit-doesnt-recognize-amend-on-git-windows – Michael Freidgeim Mar 09 '23 at 00:28
You can, but it will have to rewrite your entire history to do so.
Signing a commit changes the commit which changes its commit ID. Since the commit ID depends on the previous commit ID, all commits after that have to be changed. And you're signing them all anyway.
If it's a personal repository that nobody else is working on, then it's not a problem. If it's a repository with other collaborators, treat it like doing a major rebase.
You'd do it with git filter-branch
to redo every commit with the -S
option.
git filter-branch --commit-filter 'git commit-tree -S "$@";' -- --all
As for not having to type in your passcode for every commit, you need to configure gpg
to use a gpg-agent. If you're familiar with ssh-agent
it's a similar idea, it's a little process that you give the password to once and keeps it stored in memory for you. How you do that depends on your operating system and setup. On OS X I let GPG Tools take care of it.

- 153,029
- 25
- 195
- 336
-
2
-
1This worked great, thanks. The answer might be improved by explaining the `filter-branch` command a bit - I'm not familiar with `commit-tree` or `filter-branch` at all so this all looks like magic. – taylorthurlow Mar 22 '18 at 17:35
-
1I get this error when I run the command: `error: gpg failed to sign the data could not write rewritten commit`. – David DeMar Oct 08 '18 at 16:11
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" = "user@domain.com" ];
then git commit-tree -S "$@";
else git commit-tree "$@";
fi' HEAD
This is useful if, for some reason, you want to sign only your own commits.

- 10,641
- 6
- 65
- 69
The use-case I wanted to solve is to sign all of my previous commits while keeping the original commits dates.
Sign relevant commits
git rebase -i --root
git commit --amend -S --no-edit && git rebase --continue # for all the relevant commits
Return commit date as author date and force push (don't forget to backup before).
git rebase --committer-date-is-author-date -i --root # return
git push origin main -f
Can be automated using the other answers.

- 31
- 1