Here's how to re-sign all of the commits on current branch while preserving original author and timestamp:
git rebase -i --root --exec 'env GIT_AUTHOR_DATE="$(git log --no-walk --format=%ad)" GIT_COMMITTER_DATE="$(git log --no-walk --format=%cd)" git commit --amend --allow-empty --no-edit --no-verify -S --reset-author'
PowerShell version of the above for Windows users:
git rebase -i --root --exec '$env:GIT_AUTHOR_DATE="$(git log --no-walk --format=%ad)"; $env:GIT_COMMITTER_DATE="$(git log --no-walk --format=%cd)"; git commit --amend --allow-empty --no-edit --no-verify -S --reset-author'
What this does:
git rebase -i --root --exec
: Starts an interactive rebase
starting from the root commit (the first commit) of your current
branch. The --exec
option allows us to specify a shell command to run after each commit.
git log --no-walk --format=%ad
is the author date (%ad
)
which we assign to GIT_AUTHOR_DATE
git log --no-walk --format=%cd
is the committer date (%cd
) which we assign to GIT_COMMITTER_DATE
- We then amend the current commit with those dates,
thereby re-signing the commit
--allow-empty
allows commits with no changes,
--no-edit
uses the existing commit
message,
--no-verify
skips pre-commit and commit-msg
hooks,
-S
signs the commit,
and --reset-author
updates the author date and time.
Finally, you may need to run:
(git pull --allow-unrelated-histories || git merge --strategy-option ours --allow-unrelated-histories) && git push
In case you have un-pushed local commits, you may need to merge before pushing, hence the git merge
fallback in the above combo.
git config commit.gpgsign true
.