signing commits with SSH keys instead of GPG
Since Git 2.34, an already existing SSH key can be used directly to sign commits, with no separate GPG installation and no dedicated key management of its own. Anyone already using SSH for push and pull gets to verified commits with considerably less overhead this way.
Table of Contents
- 1. Why sign commits at all
- 2. Why GPG signing often gets abandoned in practice
- 3. SSH signatures as an alternative since Git 2.34
- 4. Configuring Git for SSH signing
- 5. The allowed_signers file for local verification
- 6. Signing commits and checking the signature
- 7. Support on GitHub and GitLab
- 8. SSH signing and GPG signing side by side
- 9. Rolling out signing across a team
- 10. Summary
- 11. FAQ
1. Why sign commits at all
The author field of a Git commit is plain, unauthenticated text, name and email address can be set to anything with git commit --author, with no proof required that the named person actually created the commit. A cryptographic signature closes exactly that gap by proving that a commit was created using the private key belonging to a specific, verifiable identity.
Especially on projects with several contributors or with security relevant code, a verified signature builds additional trust during code review and, if something goes wrong, provides solid proof of which specific person actually stands behind a given commit. With a compromised access path, for instance a stolen push token, a strict signing requirement helps reliably tell forged commits apart from genuine ones, since an attacker without the matching private key simply cannot produce a valid signature.
2. Why GPG signing often gets abandoned in practice
GPG brings a fully separate key management system for commit signing, including a web of trust concept, its own gpg-agent process, and its own key format that has nothing to do with any SSH keys already in use. For many developers that means an entirely additional tool stack that has to be installed and maintained solely for this one purpose.
In practice, that extra overhead is exactly what often causes GPG signing to fall by the wayside despite an official policy, since gpg-agent asks for the passphrase again after every restart, key generation feels unfamiliar and complex, and error messages after a misconfiguration are rarely self explanatory. On freshly set up development machines or inside containerized build environments, GPG setup frequently fails even earlier, either due to missing entropy sources for key generation or because gpg-agent has no graphical surface at all to prompt for the passphrase in the first place.
3. SSH signatures as an alternative since Git 2.34
Since Git 2.34, Git supports a second, alternative signature format via gpg.format ssh, which internally relies on OpenSSH's own signing functionality, specifically ssh-keygen -Y sign and ssh-keygen -Y verify. That means the exact same SSH key already used to authenticate against the Git server can be used directly to sign commits as well.
That considerably lowers the barrier to entry, since no additional key pair has to be generated and no separate software has to be installed, anyone already pushing over SSH typically already has everything needed for signing.
4. Configuring Git for SSH signing
The switch happens through three configuration values: gpg.format is set to ssh, user.signingkey points to the path of the public SSH key, and commit.gpgsign enables automatic signing for every future commit, so the -S flag no longer needs to be passed manually every time.
Setting tag.gpgsign in addition applies the same automatic signing to annotated tags too, which is particularly recommended for release tags whose origin should be verifiable as well.
# Switch Git to SSH based signing
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
git config --global tag.gpgsign true
5. The allowed_signers file for local verification
For Git to actually verify an SSH signature locally, it needs a mapping between email address and public key inside a so called allowed_signers file, whose path is stored in gpg.ssh.allowedSignersFile. Every line in that file ties one email address to exactly one public key in the familiar OpenSSH format.
Without that file, Git can still sign, but neither git log --show-signature nor git verify-commit produce a meaningful result then, since the reference information about which public key belongs to which identity is simply missing.
# Point Git at the allowed_signers file
git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
# Content of the file: one line per identity
# max@mironsoft.de ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIxxxxx...
6. Signing commits and checking the signature
With commit.gpgsign enabled, every new commit gets signed automatically without any further action. Without that global setting, a single commit can still be signed deliberately with the -S option, which works well as a gradual first step before turning on automatic signing for every future commit.
For verification, git log --show-signature reports directly inside the log output whether and with which key a commit was signed, while git verify-commit produces the same proof for a single specific commit hash and fits nicely into an automated check script.
# Sign a single commit deliberately
git commit -S -m "Feature: reworked price calculation"
# Verify the signature of a specific commit
git verify-commit HEAD
7. Support on GitHub and GitLab
GitHub accepts SSH signing keys as their own key type, stored separately from the regular authentication key in the account settings, even though both can technically be the exact same key. A successfully verified commit gets the same green Verified badge there that used to be reserved exclusively for GPG signed commits.
GitLab supports SSH signatures as well, manages the associated public keys under the user settings, and marks verified commits in the web interface accordingly, so verification stays visible not just locally but across the whole team.
8. SSH signing and GPG signing side by side
The biggest practical difference lies in management overhead: SSH signing reuses key infrastructure that already exists, while GPG brings an entirely separate, parallel management layer. When it comes to revoking a compromised key, though, GPG's revocation certificate concept offers a somewhat more mature, dedicated mechanism than the SSH world does.
A clear advantage of SSH signing shows up with hardware security keys: a FIDO2 token such as a YubiKey can be used directly for signing through ssh-agent, with no need to set up a separate GPG smartcard configuration on top.
9. Rolling out signing across a team
For a binding rollout across a team, it makes sense to distribute commit.gpgsign and gpg.format ssh through a central, documented onboarding guide rather than relying on each individual developer's own configuration. On the server side, the requirement to sign can additionally be enforced technically through push rules or protected branch settings.
The allowed_signers file itself can sensibly be maintained directly inside the project repository and pulled in through a relative include path in the local Git configuration, so new team members automatically receive the current, centrally maintained list the moment they clone the repository.
| Criterion | SSH signing | GPG signing |
|---|---|---|
| Extra software required | No, uses existing OpenSSH | Yes, a separate GPG installation |
| Key reusable | Yes, the same key as for push/pull | No, a dedicated key pair is needed |
| Hardware token support | Directly via ssh-agent | Only through an extra smartcard setup |
| Revoking a compromised key | Remove manually from allowed_signers | Dedicated revocation certificate |
| Support on GitHub and GitLab | Yes, its own Verified badge | Yes, established for years |
Mironsoft
Git workflows, branching strategies, and CI hooks
Chaotic Git history and unclear branching rules across the team?
We set up clean Git workflows, clarify branching strategies for the team, and automate quality checks via Git hooks and CI pipelines so the history stays traceable.
Workflow Audit
Review the existing branching strategy and merge practice for weak spots.
Hook Automation
Set up pre-commit and pre-push hooks for linting, tests, and commit conventions.
Team Training
Teach rebase, cherry-pick, and conflict resolution hands-on across the team.
10. Summary
SSH Commit Signing
Core idea
gpg.format ssh signs commits with the very same SSH key already used for push and pull.
Key file
The allowed_signers file ties email addresses to public keys and enables local verification.
Verification commands
git log --show-signature and git verify-commit show and confirm the signature of a commit.
Platform support
GitHub and GitLab display SSH signed commits with the same Verified badge as GPG signed commits.