Signed commits (introduction)
Intermediate Core Git GitLab UI GitHub UI
Why this matters
The author of a commit is whatever user.name and user.email say (lesson 3.3). Nothing checks them. Anyone who can push to a repository can produce a commit that appears to be from anyone at all, and the history will look entirely normal. Signing is the fix, and some teams require it.
Anyone can be anyone
Two configuration values and a commit:
$ git config user.name "Dev Maintainer"
$ git config user.email "dev@northwind-trails.example"
$ git commit -m "chore: routine update"The commit now says it is from Dev. git log shows Dev. The platform shows Dev's avatar if that email belongs to Dev's account. Nothing is broken and nothing warns anyone: those fields are labels, not credentials.
What is verified is the push: the token or key you used identifies you, and the platform records who pushed. But the commits inside a push can claim any author, and history that came in through a merge from elsewhere carries whatever it carried.
What a signature adds
The badges you will see:
| Badge | Meaning |
|---|---|
| Verified | The signature is valid and the key belongs to the account whose email is on the commit |
| Unverified | There is a signature, but the key is unknown to the platform or does not match the author |
| No badge | The commit is not signed, which is the normal state on most projects |
A commit made in the web editor is signed by the platform itself, which is why browser edits show Verified without you configuring anything.
Starting to sign
The quickest route uses the SSH key you may already have from lesson 8.2, and needs Git 2.34 or newer:
$ git config --global gpg.format ssh
$ git config --global user.signingkey ~/.ssh/id_ed25519.pub
$ git config --global commit.gpgsign trueerror: gpg failed to sign the data:
gpg: skipped "Ana <ana@northwind-trails.example>": No secret keyThen upload the same public key again on the platform, this time as a signing key: GitLab Edit profile → SSH keys with usage Signing, GitHub Settings → SSH and GPG keys → New SSH key with key type Signing Key. The same file serves both purposes; the platform stores it twice with different roles.
The older route uses GPG, which is more work to set up and is covered in lesson 18.3 along with the details of verification, key rotation and signing tags.
If signing is configured but the key is missing, commits fail rather than silently going unsigned:
That is the failure to expect when commit.gpgsign is on and the key is not where Git thinks it is.
Do you need this?
For most people reading this course: not yet. Signing matters when
- the project requires it, usually through a protected-branch rule ("Reject unsigned commits");
- the project is public and identity claims matter;
- the organization's policy says so, often for audit reasons.
If none applies, skip it and come back when a merge request is rejected for an unsigned commit. If one does apply, the three configuration lines above plus a key upload is the whole setup.
Common mistakes
- Believing the author field proves authorship. It is a label; signing is what proves it.
- Uploading the signing key only as an authentication key. GitLab and GitHub keep the two roles separately; add it in both roles, or the badge stays Unverified.
commit.gpgsign truewithout a working key. Every commit fails withgpg failed to sign the data. Either fix the key or set it back tofalse.- A signing email that differs from the commit email. The badge shows Unverified; the addresses must match, and the address must be verified on your account.
- Expecting Verified to mean reviewed. It says who, not whether the change is any good.
Try it yourself
Goal: see how little the author field guarantees.
- In a scratch repository (not the playground):
mkdir ~/author-demo && cd ~/author-demo && git init. - Set a different identity for this repository only:
git config user.name "Someone Else"andgit config user.email "someone@example.com". - Make an empty commit:
git commit --allow-empty -m "chore: demonstrate authorship". - Run
git log -1and read the Author line. - Delete the folder:
cd ~ && rm -rf author-demo.
Expected result: the commit is attributed to "Someone Else" and nothing objected.
Show solution
Local configuration decides the label (lesson 3.4); nothing verifies it. That is why signing exists, and why platforms show a Verified badge only when a signature backs the claim. Note that pushing this commit would still be attributed to your account as the pusher, which is the one thing the platform does check.