C.W.K.
Stream
Lesson 03 of 04 · published

Hooks, Signing, and Local Gates

~20 min · hooks, signing

Level 0Untracked Rookie
0 XP0/47 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

Hooks and signing turn intent into enforcement

Git hooks are scripts in .git/hooks/ that fire at lifecycle events: before-commit, after-commit, before-push, before-receive, etc. Two categories matter for teams. Client-side hooks (pre-commit, commit-msg, pre-push) run on the developer's machine and catch problems before they leave the laptop — formatting, linting, banned-string detection, basic test runs. Server-side hooks (pre-receive, update) run on the server and reject pushes that violate policy — they are the last line of defense and the only one that cannot be bypassed by a careless contributor.

The practical client-side stack today: pre-commit (the Python tool, not the hook name) or Husky (Node ecosystem) configures hooks declaratively from a YAML or package.json. A hook config can run formatters (Prettier, Black), linters (ESLint, Ruff), and custom checks (no console.log, no TODO in production code, secret scanning). Each push surfaces violations early when they are cheap to fix, instead of after CI runs minutes later.

Commit signing is the second hardening layer. With git commit -S (or commit.gpgsign = true), Git signs the commit with your GPG or SSH key. GitHub's "Verified" badge confirms the signature matches a key registered to the author. This blocks impersonation: an attacker who steals a developer's account password but not their signing key cannot push commits that pass branch protection requiring signed commits. SSH commit signing (Git 2.34+) is easier than GPG and works with the same keys you already use for SSH push.

Configure once. git config --global commit.gpgsign true turns on signing for every commit. git config --global gpg.format ssh uses SSH keys instead of GPG. git config --global user.signingkey ~/.ssh/id_ed25519.pub picks the key. Branch protection rule "Require signed commits" rejects unsigned pushes. Combined with hook-enforced format and content rules, the team's standards are encoded in tooling rather than relying on careful humans.

Code

pre-commit framework — declarative hooks·text
# .pre-commit-config.yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-merge-conflict
      - id: detect-private-key
      - id: check-added-large-files
        args: ['--maxkb=500']
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.6.9
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format
  - repo: https://github.com/igorshubovych/markdownlint-cli
    rev: v0.41.0
    hooks:
      - id: markdownlint

# Install:
# pip install pre-commit
# pre-commit install
SSH commit signing setup·bash
# Use the SSH key you already use for git push:
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub

# Sign every commit by default:
git config --global commit.gpgsign true
git config --global tag.gpgsign true

# Trust your key for verification (one-time):
echo "$(git config user.email) $(cat ~/.ssh/id_ed25519.pub)" \
  > ~/.config/git/allowed_signers
git config --global gpg.ssh.allowedSignersFile ~/.config/git/allowed_signers

# Tell GitHub about the signing key (Settings → SSH and GPG keys → Signing key)

# Verify a commit signature locally:
git log --show-signature -1

External links

Exercise

On a real project, install pre-commit with at least three checks (whitespace, secret detection, language-appropriate linter). Run pre-commit run --all-files and fix anything it flags. Separately, set up SSH commit signing on your machine with the steps in the lesson, push a signed commit, and verify the GitHub UI shows the "Verified" badge. Note in writing one check you would add to your team's hook config.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.