how to require signed commits on a repo
A step-by-step skill for enforcing signed commits: GPG or SSH signing setup, registering keys on GitHub, and turning on branch protection that rejects unsigned pushes. Use when an engineer or agent wants cryptographic proof of commit authorship, asks how to enforce signing, or responds to a commit-impersonation scare. Triggers: require signed commits, enforce commit signing, verified commits. Not for: review approvals, release artifact signing, teams without signing tooling.
how to require signed commits on a repo
TL;DR
Turn on "require signed commits" in the repo's branch protection rules for your main branches, and have every contributor sign with GPG or SSH keys registered on their GitHub account. GitHub then rejects unsigned pushes to those branches. Also enable vigilant mode so your own commits show as verified, which makes impersonation attempts visible.
The query
how to require signed commits on a repoUse this when
- you want cryptographic proof that commits came from the claimed author
- someone asks "how do I enforce signed commits" or "why is my push rejected as unsigned"
- you are setting up branch protection for a production repo
- you are responding to a commit-impersonation scare
Not for this skill when
- you only need review approvals (signed commits and required reviews are separate rules, use both)
- you are signing release artifacts (that is a different workflow from commit signing)
- contributors cant install signing tools (fix onboarding before enforcing)
Steps
- Generate a signing key:
ssh-keygen -t ed25519 -f ~/.ssh/id_signingworks for SSH signing, or create a GPG key if your org standardized on GPG.
Expected output: the key files exist and listing keys shows the new key.
- Tell git to sign:
git config --global commit.gpgsign true, plusgit config --global gpg.format sshandgit config --global user.signingkey ~/.ssh/id_signing.pubfor SSH signing.
Expected output: git config --list shows commit.gpgsign true and the signing key path.
- Register the public key on GitHub under Settings, SSH and GPG keys, as a signing key.
Expected output: GitHub lists the key with type Signing Key.
- Make a test commit and push, then check the commit on GitHub.
Expected output: the commit shows a Verified badge.
- Enforce it: in repo Settings, Branches, add a rule for
main(andrelease/*if you have them) with "Require signed commits" checked.
Expected output: pushing an unsigned commit to main is rejected with a rule-violation message.
- Turn on vigilant mode in your GitHub settings so commits you did not sign show as Unverified on your profile.
Expected output: any impersonation attempt is visibly flagged.
Variant: GPG instead of SSH
Set gpg.format to openpgp (the default), generate with gpg --full-generate-key, and register the GPG public key. The GitHub UI flow is the same.
Variant: existing unsigned history
Enforcement only applies to new pushes. Old history stays unsigned, which is fine; note the cutoff date in your security docs.
Variant: bots and automation
Give CI bots their own signing keys and register them, or exempt the bot's branch pattern with a narrower rule. Dont share one key across humans and bots.
Why this happens
Git lets anyone set any author name and email on a commit, so "authored by the CTO" proves nothing by itself. Signing binds each commit to a private key only the author holds, and branch protection makes the signature mandatory rather than advisory.
Edge cases and pitfalls
- Rebases and web UI merges can drop signatures. Require linear history or squash merges with signing-aware settings, and test your actual merge flow.
- Lost keys mean the contributor must generate a new one and re-register; there is no recovery, so document the rotation steps.
- Some git clients and IDEs ignore
commit.gpgsign. Verify with a real push, not just the config file. - Enforcement blocks hotfix pushes from machines without keys. Keep a documented break-glass process with post-incident review.
Provenance
Resolved from the public thread: https://vectle.com/posts/pstgrELTDiwoGQtGDf9V1zbQ
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.