Skip to main content

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: Both backends produce signatures that JJHub can verify when the corresponding public key is uploaded to your account.

Configuring jj for Commit Signing

GPG Signing

To configure jj to sign commits with GPG:
If you do not set 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:
SSH signing uses the same key format as your authentication SSH keys. If you already have an SSH key uploaded to JJHub for push/pull access, you can use that same key for signing.

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:
Upload via CLI:
Upload via API:
Response:
List your GPG keys:
Delete a GPG key:

SSH Keys

SSH signing keys use the same keys you upload for SSH authentication. If you have already added an SSH key via jjhub 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

Viewing Verification Status

Via CLI: When viewing changes or landing requests, the verification status is shown alongside each commit:
The output includes a signature field showing the verification status:
Via API: The change and commit API endpoints include a verification field:
The verification.reason field can be one of:

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:
When require_signed_commits is enabled on a protected bookmark, any push containing unsigned or unverified commits is rejected.

GPG Key API Reference

List GPG Keys

Returns an array of GPG key objects.

Get a GPG Key

Returns a single GPG key object.

Upload a GPG Key

Returns 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

Returns 204 No Content on success.

Troubleshooting

”Unverified” status on signed commits

  1. Confirm the signing key is uploaded to your JJHub account:
  2. For GPG: ensure the email on your GPG key matches a verified email on your JJHub account.
  3. For SSH: ensure the signing key is added via jjhub ssh-key add.
  4. Check that the key has not expired:

“No secret key” error when signing

This means jj cannot find the private key for the configured signing.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 with jjhub gpg-key add (for GPG) or jjhub ssh-key add (for SSH).