skip to content

Why do amend, rebase, and cherry-pick drop a Git commit's existing signature?

level: seniorimportance: should knowfreq 26%

answer

  1. Git objects are content-addressed and immutable
  2. Rewriting builds new objects, it never edits
  3. Committer and parents change even when author does not
  4. The signature lives inside the object it signs
  5. Re-signing makes the attestation yours

basics

~20 s

Those operations create new commit objects rather than editing old ones, and a signature only validates the exact object it was made over. The new commit has different parents, committer or timestamp, so the old signature cannot carry over and must be replaced.

solid answer

~50 s

A signature is stored in the commit object and computed over that object's content, so it is valid only for those exact bytes. `git commit --amend`, `git rebase` and `git cherry-pick` do not modify commits — they build new ones, with a new committer line, a new timestamp and usually different parents. Copying the old signature onto that new object would produce a signature that does not verify, so Git simply does not carry it over, and the result is unsigned unless you ask for a fresh signature. You get one with `-S` on the rewriting command (`git commit --amend -S`, `git rebase -S`, `git cherry-pick -S`, `git merge -S`), or by setting `commit.gpgSign` so the commits created during those operations are signed as they are produced — at the cost of one signing operation per replayed commit, which is why an agent matters during a long rebase.

code

bash · 8 lines
bash
git commit --amend -S --no-edit

git rebase -S origin/main

git cherry-pick -S <sha>

# Where did the signatures stop?
git log --pretty="%h %G? %GS %s" origin/main..HEAD

go deeper

for a junior

Remember that rebase and amend create new commits rather than editing existing ones, so anything attached to the old commit — including its signature — does not come along.

for a middle

Explain which fields change (parents, committer, timestamp), why that invalidates a signature over the object, and how -S or commit.gpgSign restores signing during the rewrite.

for a senior

Bring the operational angle: automate signing because manual flags get forgotten on the rewrite that matters, audit a range with %G?, and recognise that re-signing moves the attestation to you.

for a principal

Reconcile the policy with the workflow — a rewrite-heavy integration model and a per-commit signing requirement pull against each other, so decide which commits must be attested and by whom before mandating either.

## Commits are immutable Git objects are content-addressed: an object's id is the hash of its bytes, so "changing a commit" is not an operation Git offers. Every command that appears to edit history — amend, rebase, cherry-pick, revert, squash, filter tools — actually constructs **new** commit objects and moves refs to point at them. The originals stay in the object database until they become unreachable and are eventually pruned. ## Why the signature cannot ride along The signature is stored in the commit object itself, as a header alongside `tree`, `parent`, `author` and `committer`, and it is computed over that object's content. A rewritten commit differs from its predecessor in at least one of those fields: - **Parents** change whenever a commit is replayed onto a different base — that is what rebase and cherry-pick are for. - **Committer line and committer timestamp** are rewritten to the person and moment of the rewrite, even when the author line is preserved. - **Tree** changes if conflicts were resolved differently, or if the message or content was edited during an amend. Any one of those makes the old signature a signature over different bytes. Verifying it would fail. So the rewrite produces an unsigned commit rather than one carrying an inherited signature that would report as bad — which is the honest behaviour: an unsigned commit correctly says "nobody attests to this", whereas a broken signature would say "someone tampered". ## Re-signing Every history-creating command takes the signing option: - `git commit --amend -S` - `git rebase -S` (also spelled `--gpg-sign`) - `git cherry-pick -S` - `git merge -S` Alternatively, set `commit.gpgSign` to true and the commits these operations create are signed as they are produced. The documented caution is real: a rebase of forty commits means forty signing operations, so run an agent that caches the passphrase, or expect a long conversation with the prompt. `--no-gpg-sign` is the per-command opt-out when you deliberately want an unsigned result. One subtlety worth naming: re-signing means *you* now attest to those commits. If you rebase someone else's signed branch, the commits keep their author lines but the signatures become yours. That is not a bug — you are the one who produced these new objects — but it does mean the original signer's attestation is gone, and if it mattered you should preserve the original commits (for example by merging rather than rebasing) instead of re-signing over the top. ## Tags Tag signatures behave the same way and bite harder. An annotated tag object names the commit it points at by hash and is signed over that content. If the commit is rewritten, the tag still points at the old commit — which may now be unreachable from any branch — and creating a tag on the new commit means creating and signing a new tag object. Release processes that sign tags therefore have to run *after* history is final, never before a planned rebase. ## Practical consequences A team that requires signed commits and also rebases heavily has to make signing automatic, because manual `-S` will be forgotten on exactly the rewrite that matters. A team whose integration step rewrites commits on the receiving side should understand that whatever signatures the author made do not survive that rewrite — the resulting commits are attested by whoever or whatever performed it, if by anyone. And when you diagnose "my commits were signed yesterday and are unsigned today", the first question is what rewrote them: an amend, a rebase onto an updated base, or a cherry-pick into a release branch. `git log --pretty="%h %G? %GS %s"` over the range shows immediately where the signatures stop. ## Interview framing Lead with immutability — rewriting creates new objects — then explain that the signature is part of the object and covers fields the rewrite changes. Name the `-S` options and `commit.gpgSign`, mention the passphrase-per-commit reality of a long rebase, and finish with the judgement point: re-signing transfers the attestation to you.

  • Why does Git leave the rewritten commit unsigned rather than copying the old signature?
    Because the copied signature would not verify against the new object's bytes and would report as a bad signature — the status that means tampering. An unsigned commit states the truth: nobody has attested to this object. Failing honestly is more useful than producing an alarm that everybody learns to ignore.
  • You rebase a colleague's signed branch onto main. Whose signatures do the resulting commits carry?
    Yours, if you re-sign; otherwise none. The author lines still name your colleague, but the commit objects are new and their original signatures are gone. If preserving their attestation matters, integrate with a merge that keeps the original commits instead of replaying them.
  • What happens to a signed tag when the commit it points at is rewritten?
    Nothing — the tag object still points at the original commit and its signature is still valid for it, but that commit may no longer be reachable from any branch. Tagging the rewritten commit requires creating and signing a new tag object, which is why release tags are cut after history is final.

saying these in an interview costs you the question

  • Thinks rebase edits commits in place
  • Expects signatures to survive because the author is unchanged
  • Believes the signature is metadata stored outside the object
  • Assumes commit.gpgSign cannot apply during a rebase
  • Ignores that re-signing transfers attestation to the rewriter

context