Keeping signatures valid through rebase and squash Jump to heading
A signature covers the exact bytes of a commit object: its tree, its parents, its author and committer lines and its message. Change any of those and you have a different commit, which the old signature does not cover. Every history-rewriting operation — rebasing onto a newer base, squashing fixups, amending a message, even a rebase that changes nothing but the parent — therefore produces commits that are either freshly signed or unsigned. Teams that enforce signing discover this the first time a perfectly signed branch fails the gate after a routine rebase. This page shows how to make re-signing automatic and how to choose merge methods that keep signatures meaningful, as part of the commit verification gates topic.
When to use this approach Jump to heading
- Your gates verify signatures, and contributors rebase, squash or amend before merging.
- Branches pass the signature check when first pushed but fail after being updated on top of a newer base.
- You use the forge’s squash or rebase merge buttons and want to understand what happens to signatures.
- You maintain long-running branches that are periodically rebased, as described in keeping a long-lived branch in sync with main.
Step 1 — Understand why a rebase strips signatures Jump to heading
A rebase replays each commit onto a new parent. The new commit has a different parent hash, so it is a different object, and Git has to decide whether to sign it. It signs only if signing is turned on for the person running the rebase.
# Verification: compare signature status before and after a rebase
git log -2 --format='%h %G?' feature # G G
git rebase main feature
git log -2 --format='%h %G?' feature # N N if signing is not automatic Step 2 — Turn on automatic signing for every commit Git creates Jump to heading
The commit.gpgSign setting tells Git to sign every commit it writes, including the ones produced by rebase, cherry-pick, amend and merge --squash. It is the single most important setting for keeping signatures through rewrites.
git config --global commit.gpgSign true
git config --global tag.gpgSign true # annotated tags too
# For SSH signing, also make sure the format and key are set
git config --global gpg.format ssh
git config --global user.signingKey ~/.ssh/id_ed25519_signing.pub With this on, a rebase re-signs each replayed commit as it writes it, so S1' and S2' above carry fresh signatures from the person who ran the rebase.
# Verification: rebase again and every rewritten commit is signed
git rebase main feature && git log main..feature --format='%h %G?' That last point has a consequence worth stating: after a rebase, the signature belongs to whoever ran it, not necessarily the original author. If Alice rebases Bob’s commits, they end up signed by Alice. The author field still says Bob, and the committer field says Alice. For most gates that is acceptable — the person who rewrote the commit vouches for it — but a gate that requires signer to equal author will reject it.
Step 3 — Re-sign a branch that was rewritten without signing Jump to heading
If someone already rebased without signing turned on, the fix is to rewrite each commit once more with a signature. The --exec option runs a command after each replayed commit.
# Re-sign every commit on the branch since it diverged from main
git rebase --exec 'git commit --amend --no-edit -S' "$(git merge-base main HEAD)"
git log main..HEAD --format='%h %G?' # all G ⚠️ SAFETY WARNING: This rewrites every commit on the branch, so the branch must be force-pushed afterwards. Use
git push --force-with-lease, which refuses if someone else pushed to the branch in the meantime. If anything goes wrong, the pre-rewrite tip is in the reflog:git reset --hard ORIG_HEADrestores it immediately after the rebase, orgit reflog featurefinds it later.
Step 4 — Choose a merge method that keeps signatures meaningful Jump to heading
The forge’s merge buttons are where most signature loss happens, because the forge — not the contributor — creates the final commits.
Three workable policies follow from that table. Use merge commits, and contributor signatures stay in history. Use forge squash or rebase, and accept the forge’s signature as the attestation — pin and trust the forge key as described in verifying signatures on merge commits made by the forge. Or squash locally with signing on and fast-forward the result, which keeps one contributor signature per change at the cost of a manual step.
# Local squash that produces one signed commit, then fast-forward
git switch feature
git reset --soft "$(git merge-base main HEAD)"
git commit -S -m "Add rate limiting to the export API"
git switch main && git merge --ff-only feature Step 5 — Re-sign fixups during autosquash Jump to heading
Fixup workflows rewrite history on purpose. With commit.gpgSign on, git rebase -i --autosquash signs the folded commits automatically. Without it, every autosquash produces an unsigned branch, which is the single most common cause of “it was signed yesterday” reports.
git commit --fixup=HEAD~2 -S
git rebase -i --autosquash main # writes signed commits when commit.gpgSign is true
git log main..HEAD --format='%h %G? %s' The full fixup workflow is in using fixup commits and autosquash during review.
Validation checklist Jump to heading
Frequently Asked Questions Jump to heading
Can Git keep the original author’s signature through a rebase? Jump to heading
No. The signature covers the parent hash, which changes, so the original signature no longer matches the new commit. Only the person who creates the new commit can sign it. If preserving the original signature matters, merge instead of rebasing.
Does git cherry-pick sign the new commit? Jump to heading
Yes, when commit.gpgSign is true or when you pass -S. A cherry-picked commit is a new object, so the same rule applies as for a rebase. Backports made by automation need the automation’s own key.
Why does the gate reject a commit I only amended to fix a typo? Jump to heading
Amending creates a new commit. If you amended without signing — for example with commit.gpgSign unset and no -S — the new commit is unsigned. Amend again with -S, or turn on automatic signing so it never happens.
Related Jump to heading
- Commit Verification Gates — the parent topic.
- Squash vs Merge vs Rebase Decision Matrix — the wider trade-off this page narrows to signatures.
- Verifying a Range of Commits in CI, Not Just the Tip — the gate that catches unsigned rewrites.
- Safe Git Rebase -i for Shared Branches — rewriting history without hurting collaborators.