Git Course 0%

Signed commits (introduction)

Intermediate Core Git GitLab UI GitHub UI ≈ 6 min

What you will learn

  • Why anyone can commit under any name, and why that matters
  • What signing adds and what the Verified badge on GitLab and GitHub means
  • The quickest way to start signing with a key you already have

After this lesson you can

  • I understand the Verified badge and can enable signing if my team asks for it

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:

Terminal
$ 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:

Terminal
$ git config --global gpg.format ssh
$ git config --global user.signingkey ~/.ssh/id_ed25519.pub
$ git config --global commit.gpgsign true
error: gpg failed to sign the data:
gpg: skipped "Ana <ana@northwind-trails.example>": No secret key

Then 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 true without a working key. Every commit fails with gpg failed to sign the data. Either fix the key or set it back to false.
  • 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.

  1. In a scratch repository (not the playground): mkdir ~/author-demo && cd ~/author-demo && git init.
  2. Set a different identity for this repository only: git config user.name "Someone Else" and git config user.email "someone@example.com".
  3. Make an empty commit: git commit --allow-empty -m "chore: demonstrate authorship".
  4. Run git log -1 and read the Author line.
  5. 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.

Check yourself

1. What does the author name on a commit prove?
2. Your commit shows Unverified on GitHub although you signed it. Most likely cause?
3. When does a team usually require signed commits?

Key terms

Commit Hash (SHA) Protected branch