Home / Alt manpages / gitformat-signature(5)

  • gitformat-signature(5)
  • File format
  • linux

Choose and Verify Git Signature Formats Without Guesswork

You will finish with a practical way to identify how Git stores signatures, select the signing format for a repository, and verify signed commits or annotated tags without confusing cryptographic validity with trust in the person behind a key. The examples match Git 2.43.0 from the git-man package installed on this machine.

Allow about fifteen minutes. You need Git and a repository. Signing also needs the external program and key material for the format you choose; this guide does not generate keys, change an agent or ask you to trust an unfamiliar key. The inspection commands are ordinary user commands. No example needs sudo.

1. Check the local Git version and the signing interface

Start by recording the version that will interpret your repository configuration:

$ git --version
git version 2.43.0
$ git commit -h 2>&1 | grep -E -- '-S|gpg-sign'
                  [(--trailer <token>[(=|:) <value>])...] [-S[<keyid>]]
    -S, --[no-]gpg-sign[=<key-id>]

The manpage describes signatures on Git objects and transactions. For everyday work, the useful object cases are signed annotated tags and signed commits. A signed tag appends its detached signature to the tag object. A signed commit stores the signature as a multiline gpgsig header, with continuation lines prefixed by a space.

Checkpoint: if your installed command does not show -S, stop here and read that installation's documentation. Do not copy a signing command from a different Git release into an unverified script.

2. Inspect the objects before changing configuration

Use Git's object printer to see what is actually stored. This is read-only and works for unsigned objects too:

$ git cat-file -p HEAD
tree <tree-object-id>
parent <parent-object-id>
author Example User <[email protected]> <timestamp>
committer Example User <[email protected]> <timestamp>

commit message
$ git cat-file -p <annotated-tag-name>
object <commit-object-id>
type commit
tag <tag-name>
tagger Example User <[email protected]> <timestamp>

tag message

Replace the angle-bracketed values with values from your repository. An unsigned commit has no gpgsig header. An unsigned annotated tag has no signature block after its message. Do not hand-edit either object: changing its contents changes its object ID and can break references or published history.

3. Choose the backend deliberately

Git selects the signature format with gpg.format. The current upstream configuration documentation calls the values openpgp, x509 and ssh; the Git 2.43.0 signature-format manpage labels the corresponding blocks gpg, x509 and ssh. For the local Git configuration, use the documented configuration value, not the ASCII armour heading:

$ git config --local gpg.format ssh
$ git config --local --get gpg.format
ssh

--local writes this repository's .git/config. If you want to test a value without writing anything, use a one-command override instead:

$ git -c gpg.format=ssh config --get gpg.format
ssh
$ git -c gpg.format=x509 config --get gpg.format
x509

Choose the format that matches the verification ecosystem your collaborators already use. openpgp uses the OpenPGP backend, ssh uses SSH signing, and x509 uses X.509 signing. Git may call different helper programs for these backends. A format setting is not a key, certificate or trust decision, so changing it does not make signing work by itself.

Security checkpoint: inspect the effective settings before signing:

$ git config --show-origin --get-regexp '^gpg\.'
file:.git/config	gpg.format ssh

The output can include global and system configuration, and it can expose helper paths. Review it before using a shared repository or automation account. If you decide not to keep the repository setting, remove only that setting with git config --local --unset gpg.format; Git then falls back to its normal default. That undo command changes configuration, so run it only after checking the exact key with --get-regexp.

4. Create or inspect a signed commit

Once the selected backend and key material are ready, sign a normal commit with -S. Supplying an explicit key ID is optional and backend-specific:

$ git commit -S -m 'Record the release decision'
[main <commit-id>] Record the release decision
$ git show --format=raw --no-patch HEAD
commit <commit-id>
tree <tree-object-id>
gpgsig -----BEGIN <signature-type> SIGNATURE-----
 <continuation-lines-prefixed-by-a-space>

The exact armour heading and helper output depend on the selected format. Do not compare the signature text byte-for-byte with a different backend. The structural check is the gpgsig header and its space-prefixed continuation lines.

If signing fails, keep the commit unsigned and investigate the helper's error, configured key and agent. Do not disable verification or paste private key material into a repository. If the commit has not been created, there is nothing to undo. If you accidentally committed sensitive material, stop and use your normal incident and history-rewrite process rather than treating a new signature as a fix.

5. Verify the object and read the result carefully

Verify a commit with the command intended for commits:

$ git verify-commit -v HEAD
gpg: Good signature from "Example User <[email protected]>"
tree <tree-object-id>
parent <parent-object-id>
author Example User <[email protected]> <timestamp>
committer Example User <[email protected]> <timestamp>
$ printf 'verification status: %s\n' "$?"
verification status: 0

For an annotated tag, verify the tag name rather than the commit it points to:

$ git verify-tag -v <annotated-tag-name>
$ printf 'verification status: %s\n' "$?"
verification status: 0

A successful verification means the signature matches the signed payload and the verifier accepts the available key or certificate information. It does not, on its own, prove that the identity belongs to the person you expected. Read the fingerprint, certificate chain or SSH allowed-signers result according to your organisation's trust process. A warning about an uncertified key is not the same as a cryptographic failure, but it is a reason to pause before accepting authorship or release provenance.

6. Diagnose the common boundary errors

  • No signature found: inspect the object with git cat-file -p. You may be verifying an unsigned commit, a lightweight tag, or the wrong object type.
  • Bad signature: the payload or signature is not a matching pair. Fetch the intended object again and check that you are not verifying a rewritten local history.
  • Unknown or untrusted identity: verify the key fingerprint or certificate through a channel you already trust. Do not solve this by lowering trust settings globally.
  • Signing helper failure: check gpg.format, the relevant helper program and key availability. Git's signature format controls how signing is performed; it does not install the backend.

The visible ASCII armour is useful for recognising a format, but the object's position matters more: tags carry the block in the tag payload, commits carry it in gpgsig, and a merge of a signed tag can carry the whole tag object in a mergetag header. Preserve whitespace when inspecting those headers; a continuation line that loses its leading space is no longer the same Git object representation.

Done means

  • You recorded the Git version used by the workflow.
  • You identified whether the object is a signed commit or an annotated tag.
  • You selected gpg.format to match the agreed verification ecosystem.
  • git verify-commit or git verify-tag returned status 0.
  • You checked the identity and trust evidence separately from the cryptographic result.