Signed Tags

Signed Tags and Verifying Provenance

Anyone who can push can create a tag named v1.1.0. A signed tag carries a signature in the tag object, so users can verify who made the release. Git 1,932 signs with OpenPGP (GPG) by default, and since Git 2.34 also with an SSH key (Signing Commits compares them). Sam signs with the SSH key the server of Git's Transport Protocols accepts, replacing the not yet pushed v1.1.0:

Signing a release tag with an SSH key and verifying itShell
git config gpg.format ssh
git config user.signingKey ~/.ssh/id_ed25519.pub
echo "sam@example.com $(cat ~/.ssh/id_ed25519.pub)" > ~/.ssh/allowed_signers
git config gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
git tag -f -s v1.1.0 -m "BookNest 1.1.0: GET /api/genres"
git tag -v v1.1.0
git push -q --follow-tags
Output
Updated tag 'v1.1.0' (was 5eee635)
Good "git" signature for sam@example.com with ED25519 key
  SHA256:dDyqIq8IYgZL9UIYXW/9qlZz91N3CZexZFO+SUfkdPM
object 5f14f7252e38c4b234bf77b36dcf7c34182ecb34
type commit
tag v1.1.0
tagger Sam Rivera <sam@example.com> 1790308500 +0800
BookNest 1.1.0: GET /api/genres

-s implies -a; -f replaced the unsigned tag, safe only because it was never pushed. The allowed signers file maps email addresses to trusted public keys. git tag -v exits non-zero on a bad signature, and on an unsigned tag such as v1.0.0 prints "error: no signature found". A signature proves that a key holder tagged exactly this commit, and through its hash exactly this tree. tag.gpgSign true signs every annotated tag.