vcs-identity-check
Verify the VCS identity before committing
so the commit is attributed correctly,
and recommend commit signing when it isn't configured.
Procedure
Read the identity for the VCS in use:
- git →
git config --show-scope --get user.name
and git config --show-scope --get user.email
(--show-scope is git ≥2.26;
it prints the scope —
local / global / system —
alongside the value);
- hg →
hg config ui.username,
then split on the last <…> pair into name and email
(e.g. Petr Korobeinikov <pk@example.com> →
name Petr Korobeinikov, email pk@example.com);
if there is no <…>,
treat the whole string as name and the email as unset;
- jj →
jj config get user.name / user.email.
Check:
- name is non-empty,
has ≥2 whitespace-separated tokens,
and is not a literal email.
The two-token rule assumes First Last conventions;
for users with a single-token mononym
(some Indonesian or Icelandic naming patterns),
accept the value on the user's explicit confirmation
and skip this sub-check;
- email is non-empty,
contains exactly one
@,
with at least one character on each side.
Read signing config:
- git →
git config commit.gpgsign,
git config tag.gpgsign,
git config user.signingkey,
git config gpg.format;
- jj →
jj config get signing.behavior
and jj config get signing.backend.
Classify into one of three states:
- Configured —
commit.gpgsign=true,
user.signingkey non-empty,
gpg.format set
(missing tag.gpgsign=true is a soft warning, not broken);
- Not configured —
commit.gpgsign unset or false,
and user.signingkey empty;
- Broken —
anything else
(e.g.
commit.gpgsign=true with empty user.signingkey) —
commits will fail to sign at runtime.
This step is informational
and does not block the commit by itself.
Short-circuit when prior commits already match.
If the same author has a prior commit in this repo
whose signing intent matches the current config,
skip the confirmation in step 5 and the signing recommendation —
the user has implicitly validated this setup before
by committing under it.
For git, run
git log -1 --author="<email>" --pretty=format:'%G?'
and treat as a match when:
- prior commit carries a signature (
%G? ≠ N)
and current signing is Configured; or
- prior commit has no signature (
%G? = N)
and current signing is Not configured.
This compares intent (sign / don't sign), not the key,
so it works for GPG and SSH alike
regardless of how user.signingkey is written
(key ID, fingerprint, with or without 0x… prefix,
or a public-key file path).
Anything else — no prior commit by this author,
Broken state, or non-git VCS — falls through to step 5.
Show the resolved values and ask the user to confirm —
«<First> <Last> (from <scope>) —
correct order, no typo?».
<scope> is what git reported (local / global / system);
for hg/jj, name the source file if available, otherwise omit.
Order can't be detected automatically;
confirmation is required.
In the same message:
- signing Not configured →
include the recommendation from the Signing section below;
- signing Broken →
name the inconsistent settings explicitly
and treat it as fix-now, not a suggestion.
If any identity check fails or the user rejects, stop.
Do not proceed to the commit.
Fix
- git, repo-local:
git config --local user.name "First Last"
(and user.email).
- git, global: same with
--global.
- hg:
[ui] username = First Last <you@example.com> in ~/.hgrc.
- jj:
jj config set --user user.name "First Last"
(and email).
Re-run the checks after fixing.
Signing
Signing commits is a good practice:
it lets reviewers verify a commit really came from the stated author,
and platforms like GitHub / GitLab / Gitea show a «Verified» badge
on signed commits.
Recommend it whenever it isn't configured.
Two formats; pick what fits the user's setup:
- GPG —
the traditional path,
works everywhere git is hosted;
requires generating a GPG key and uploading the public key
to the host's «GPG keys» settings.
- SSH —
reuses an existing SSH key,
no extra tooling beyond
git ≥2.34 and ssh-keygen;
fits well when GPG isn't already in use.
Requires uploading the public key as a «signing key»
(separate from the auth key) on the host.
Setup (git, global):
GPG:
git config --global gpg.format openpgp
git config --global user.signingkey "<KEY-ID>"
git config --global commit.gpgsign true
git config --global tag.gpgsign true
SSH:
git config --global gpg.format ssh
git config --global user.signingkey "<path-to-public-key>"
git config --global commit.gpgsign true
git config --global tag.gpgsign true
Then upload the public key to the host's signing-keys settings.
1---2name: vcs-identity-check3description: Verifies the VCS author identity (name + email) is set correctly before committing, and recommends configuring commit signing (GPG or SSH) when it isn't already set up.4---56# vcs-identity-check78Verify the VCS identity before committing9so the commit is attributed correctly,10and recommend commit signing when it isn't configured.1112## Procedure13141. Read the identity for the VCS in use:15 - git → `git config --show-scope --get user.name`16 and `git config --show-scope --get user.email`17 (`--show-scope` is git ≥2.26;18 it prints the scope —19 `local` / `global` / `system` —20 alongside the value);21 - hg → `hg config ui.username`,22 then split on the last `<…>` pair into name and email23 (e.g. `Petr Korobeinikov <pk@example.com>` →24 name `Petr Korobeinikov`, email `pk@example.com`);25 if there is no `<…>`,26 treat the whole string as name and the email as unset;27 - jj → `jj config get user.name` / `user.email`.282. Check:29 - **name** is non-empty,30 has ≥2 whitespace-separated tokens,31 and is not a literal email.32 The two-token rule assumes First Last conventions;33 for users with a single-token mononym34 (some Indonesian or Icelandic naming patterns),35 accept the value on the user's explicit confirmation36 and skip this sub-check;37 - **email** is non-empty,38 contains exactly one `@`,39 with at least one character on each side.403. Read signing config:41 - git → `git config commit.gpgsign`,42 `git config tag.gpgsign`,43 `git config user.signingkey`,44 `git config gpg.format`;45 - jj → `jj config get signing.behavior`46 and `jj config get signing.backend`.4748 Classify into one of three states:49 - **Configured** —50 `commit.gpgsign=true`,51 `user.signingkey` non-empty,52 `gpg.format` set53 (missing `tag.gpgsign=true` is a soft warning, not broken);54 - **Not configured** —55 `commit.gpgsign` unset or `false`,56 and `user.signingkey` empty;57 - **Broken** —58 anything else59 (e.g. `commit.gpgsign=true` with empty `user.signingkey`) —60 commits will fail to sign at runtime.6162 This step is informational63 and does not block the commit by itself.644. **Short-circuit when prior commits already match.**65 If the same author has a prior commit in this repo66 whose signing intent matches the current config,67 skip the confirmation in step 5 and the signing recommendation —68 the user has implicitly validated this setup before69 by committing under it.7071 For git, run72 `git log -1 --author="<email>" --pretty=format:'%G?'`73 and treat as a match when:74 - prior commit carries a signature (`%G?` ≠ `N`)75 and current signing is **Configured**; or76 - prior commit has no signature (`%G?` = `N`)77 and current signing is **Not configured**.7879 This compares intent (sign / don't sign), not the key,80 so it works for GPG and SSH alike81 regardless of how `user.signingkey` is written82 (key ID, fingerprint, with or without `0x…` prefix,83 or a public-key file path).8485 Anything else — no prior commit by this author,86 **Broken** state, or non-git VCS — falls through to step 5.875. Show the resolved values and ask the user to confirm —88 «`<First> <Last>` <email> (from `<scope>`) —89 correct order, no typo?».90 `<scope>` is what git reported (`local` / `global` / `system`);91 for hg/jj, name the source file if available, otherwise omit.92 Order can't be detected automatically;93 confirmation is required.94 In the same message:95 - signing **Not configured** →96 include the recommendation from the **Signing** section below;97 - signing **Broken** →98 name the inconsistent settings explicitly99 and treat it as fix-now, not a suggestion.1006. If any identity check fails or the user rejects, stop.101 Do not proceed to the commit.102103## Fix104105- git, repo-local:106 `git config --local user.name "First Last"`107 (and `user.email`).108- git, global: same with `--global`.109- hg: `[ui] username = First Last <you@example.com>` in `~/.hgrc`.110- jj: `jj config set --user user.name "First Last"`111 (and email).112113Re-run the checks after fixing.114115## Signing116117Signing commits is a good practice:118it lets reviewers verify a commit really came from the stated author,119and platforms like GitHub / GitLab / Gitea show a «Verified» badge120on signed commits.121Recommend it whenever it isn't configured.122123Two formats; pick what fits the user's setup:124125- **GPG** —126 the traditional path,127 works everywhere git is hosted;128 requires generating a GPG key and uploading the public key129 to the host's «GPG keys» settings.130- **SSH** —131 reuses an existing SSH key,132 no extra tooling beyond `git` ≥2.34 and `ssh-keygen`;133 fits well when GPG isn't already in use.134 Requires uploading the public key as a «signing key»135 (separate from the auth key) on the host.136137Setup (git, global):138139GPG:140141```sh142git config --global gpg.format openpgp143git config --global user.signingkey "<KEY-ID>"144git config --global commit.gpgsign true145git config --global tag.gpgsign true146```147148SSH:149150```sh151git config --global gpg.format ssh152git config --global user.signingkey "<path-to-public-key>"153git config --global commit.gpgsign true154git config --global tag.gpgsign true155```156157Then upload the public key to the host's signing-keys settings.