Commit Signing
Commit signing provides cryptographic proof that a commit was authored by a specific person. When you sign a commit, you attach a digital signature that JJHub can verify against your uploaded public key. Verified commits display a Verified badge, giving reviewers and collaborators confidence that the code was not tampered with and genuinely came from you.Why Sign Commits
- Authorship verification: Prove that a commit was created by the person who claims to have created it, not someone who happened to have push access.
- Tamper detection: If a signed commit is modified after signing, the signature becomes invalid.
- Supply chain security: In CI/CD pipelines and automated workflows, signed commits provide an audit trail of who (or what agent) produced each change.
- Protected bookmark enforcement: Repository owners can require signed commits on protected bookmarks, rejecting unsigned pushes.
Supported Key Types
JJHub supports two signing backends:| Backend | Key Type | Best For |
|---|---|---|
| GPG | RSA, Ed25519, ECDSA | Traditional PGP key infrastructure, multiple identities per key |
| SSH | Ed25519, RSA, ECDSA | Simpler setup, reuse existing SSH keys |
Configuring jj for Commit Signing
GPG Signing
To configure jj to sign commits with GPG:signing.sign-all, you can sign individual commits by passing the --sign flag to jj commands that create commits.
SSH Signing
To configure jj to sign commits with an SSH key:Uploading Your Signing Key to JJHub
For JJHub to verify your signed commits, you must upload the corresponding public key to your account.GPG Keys
Upload your GPG public key via the CLI or API. Export your GPG public key:SSH Keys
SSH signing keys use the same keys you upload for SSH authentication. If you have already added an SSH key viajjhub ssh-key add, that key is automatically available for commit signature verification — no additional upload is needed.
If you use a separate key for signing (different from your authentication key), add it as an SSH key:
Verified Commits
When JJHub receives a push containing signed commits, it automatically verifies each commit’s signature against the public keys on the author’s account.Verification Statuses
| Status | Meaning |
|---|---|
| Verified | The signature is valid and matches a key on the committer’s JJHub account. |
| Unverified | The commit has a signature, but it does not match any key on the committer’s account, or the key has expired. |
| Unsigned | The commit has no signature. |
Viewing Verification Status
Via CLI: When viewing changes or landing requests, the verification status is shown alongside each commit:signature field showing the verification status:
verification field:
verification.reason field can be one of:
| Reason | Description |
|---|---|
valid | Signature is valid and matches a trusted key |
unsigned | No signature present |
unverified_key | Signature is valid but the key is not associated with any JJHub account |
expired_key | Signature was made with a key that has since expired |
bad_signature | Signature is malformed or does not match the commit data |
Protected Bookmark Signing Requirements
Repository owners can require that all commits pushed to a protected bookmark are signed. This is configured through bookmark protection rules:require_signed_commits is enabled on a protected bookmark, any push containing unsigned or unverified commits is rejected.
GPG Key API Reference
| Method | Endpoint | Description |
|---|---|---|
GET | /api/user/gpg-keys | List your GPG keys |
GET | /api/user/gpg-keys/:id | Get a specific GPG key |
POST | /api/user/gpg-keys | Upload a new GPG key |
DELETE | /api/user/gpg-keys/:id | Delete a GPG key |
List GPG Keys
Get a GPG Key
Upload a GPG Key
201 Created with the GPG key object. Returns 422 Unprocessable Entity if the key is malformed or already associated with another account.
Delete a GPG Key
204 No Content on success.
Troubleshooting
”Unverified” status on signed commits
- Confirm the signing key is uploaded to your JJHub account:
- For GPG: ensure the email on your GPG key matches a verified email on your JJHub account.
- For SSH: ensure the signing key is added via
jjhub ssh-key add. - Check that the key has not expired:
“No secret key” error when signing
This means jj cannot find the private key for the configuredsigning.key. Verify:
Commits signed locally but show as unsigned on JJHub
This happens when the public key corresponding to your signing key has not been uploaded to JJHub. Upload it withjjhub gpg-key add (for GPG) or jjhub ssh-key add (for SSH).