Securing a Repo

Course 3 · Ch 6
Securing a Serious Repository
Branch protection in full, CODEOWNERS for automatic review routing, and signed commits for verified authorship

Course 2, Chapter 9 introduced branch protection as the structural fix for force-push dangers. This chapter covers the full set of protection options properly, adds CODEOWNERS for automatically routing reviews to the right people, and covers signed commits — proving a commit genuinely came from who it claims to.

Branch Protection, the Complete Picture

Settings → Branches → Add branch protection rule, applied to main (or any branch worth protecting):

Require a pull request before merging
No direct pushes at all (Course 2, Ch9) — every change goes through review.
Require approvals (and dismiss stale ones)
A minimum approval count, with the option to automatically dismiss an approval if new commits are pushed after it — preventing a reviewer's approval from silently covering changes they never actually saw.
Require status checks to pass
Ties to Course 2/3's Actions chapters — a failing CI run physically blocks the merge button.
Require conversation resolution
Every open review comment thread must be marked resolved before merging — stops feedback from being silently ignored.
Require signed commits
Rejects any commit that isn't cryptographically signed — covered fully below.
Restrict who can push
Limits direct push access (where it's allowed at all) to specific people or teams, even among repo collaborators.
Include administrators
Applies every rule above to repo admins too, with no bypass — removes the "but I'm the owner" exception that quietly undermines every other rule if left unchecked.
"Include administrators" is the rule most teams forget
Setting up strict protection that admins can casually bypass provides much less real protection than it appears to — most accidental force-pushes and skipped-review incidents in practice come from someone with elevated access taking a shortcut "just this once." Checking this option closes that gap.

CODEOWNERS — Automatic Review Routing

A CODEOWNERS file (in the repo root, or .github/, or docs/) maps file paths to the people or teams responsible for them — GitHub automatically requests their review the moment a PR touches a matching path.

# CODEOWNERS — paths and their required reviewers

# Default owner for everything not matched below
* @philipo

# Database migrations need a specific reviewer every time
/migrations/ @philipo @db-team

# CI/CD configuration
/.github/workflows/ @philipo

Combined with branch protection's "require approval from Code Owners," this turns review routing from a manual, easily-forgotten step ("don't forget to tag someone on the migration!") into something GitHub enforces automatically.

CODEOWNERS scales well even for a solo maintainer with occasional contributors
Even on a personal project, a CODEOWNERS file ensures that if someone else opens a PR touching a sensitive area (deployment config, database migrations), you're automatically requested as a reviewer — without needing to remember to check every incoming PR's file list manually.

Signed Commits — Proving Authorship

A commit's author name and email (set via git config back in Course 1, Chapter 1) are just text fields — trivially easy to set to anything, including someone else's identity. A signed commit adds a cryptographic signature, proving the commit was created by someone possessing a specific private key.

Setting up GPG signing

$ # Generate a GPG key (if you don't already have one)
$ gpg --full-generate-key

$ # Find the key ID
$ gpg --list-secret-keys --keyid-format=long

$ # Tell git to use it, and sign every commit by default
$ git config --global user.signingkey YOUR_KEY_ID
$ git config --global commit.gpgsign true

$ # Add the public key to GitHub: Settings → SSH and GPG keys → New GPG key

From here, every commit gets signed automatically, and GitHub shows a verification badge on the commit:

✓ Verified a1b2c3d Fix login validation bug — Philip Osztromok
Unverified f9e8d7c Some commit with the right name, wrong signature

SSH signing — a simpler alternative

Git also supports signing with the SSH key you may already have set up (Course 1, Chapter 5) — avoiding GPG entirely:

$ git config --global gpg.format ssh
$ git config --global user.signingkey ~/.ssh/id_ed25519.pub
$ git config --global commit.gpgsign true
Signed commits prove the commit, not the code's quality
A signature verifies who created this commit — it says nothing about whether the code is correct, secure, or well-reviewed. It's a complement to code review (Course 2, Chapter 7) and branch protection, not a replacement for either. Most valuable in contexts with multiple contributors where impersonation is a genuine, realistic risk — open source projects, regulated environments, anywhere identity verification matters beyond trust alone.

Command Reference

CommandWhat it does
git config --global commit.gpgsign trueSigns every commit automatically going forward
git config --global user.signingkey <id>Sets which key to sign with (GPG key ID or SSH public key path)
git commit -S -m "msg"Signs a single commit explicitly (if not signing by default)
git log --show-signatureShows signature verification status for recent commits

Chapter 6 Quick Reference

  • Branch protection (full set): require PR, require approvals (dismiss on new commits), require status checks, require conversation resolution, require signed commits, restrict pushers, include administrators
  • "Include administrators" closes the most commonly forgotten loophole — no bypass for repo owners
  • CODEOWNERS — maps file paths to required reviewers, automatically requested on matching PRs
  • Signed commits — cryptographically prove WHO created a commit, via GPG or SSH key signing
  • git config commit.gpgsign true — signs every future commit automatically
  • A signature proves authorship, not code quality — complements review and protection, doesn't replace them
  • Next chapter: large repos — Git LFS, shallow clones, sparse checkout, and monorepo strategies