Article 2: PR-only
Direct commits to main are forbidden. Every change goes through a pull request, even when you're the only reviewer, even when you're the only person on the project. The discipline of writing the change down twice is what makes the work reviewable later, including by your future self.
Article 1 was that the main branch is sacred. Article 2 follows from it directly: direct commits to main are forbidden. Every change goes through a pull request. Every change. No exceptions for hotfixes or typo fixes, no exceptions when you're the only reviewer, no exceptions when you're alone on the project. PR-only, all the time, from day one.
I've watched myself ignore this rule and pay for it. I've watched teams ignore this rule and pay for it more. The pattern is always the same: the rule looks like overhead in week one and looks like the only thing keeping the codebase legible at month eighteen. The cost is real but it's small and it's front-loaded; the value is also real and it compounds quietly until you notice that the codebases you can still read after a year are the ones that had this rule, and the ones you can't read are the ones that didn't.
What the rule actually says
PR-only is a process discipline, not a tooling decision. The tooling enforces it (branch protection on main, required reviews, status checks) but the discipline lives in the team's agreement that no commit lands on main without going through a PR first.
The version most teams adopt looks like this. You branch off main, make your change, push the branch, and open a PR. You write a description that explains what changed and why. You wait for at least one review and address the comments. CI runs and passes, you merge, and the PR closes. The branch deletes itself.
That's the loop. Five extra steps over "git commit -am 'fix' && git push origin main." Each step is small. Each step exists for a reason that takes years of doing the wrong thing to fully appreciate.
The argument I've made for the exception, and why I was wrong
I have been the engineer who said "this is a one-line fix, let me just push it." I have been the engineer who said "production is broken right now, the PR queue is the wrong tool for this." I have been the engineer who said "I'm the only one on this project, the review step is theater."
Every one of those positions has a counter that I've eventually had to learn the hard way.
The one-line fix that bypassed review was the one that took down production at 11pm because the line had a typo nobody caught. A PR with a one-line diff takes thirty seconds to review and one CI run to validate. The thirty seconds was cheaper than the incident.
The hotfix during an outage that bypassed review made the outage worse, because the change was a guess and the guess introduced a second bug. The five-minute wait for a hotfix PR review during an active incident is the cheapest insurance you have. If you don't have anyone to review it, the discipline is to call someone, a co-founder, a co-owner, anyone you trust who can read a diff. The point isn't the depth of the review; the point is that two pairs of eyes saw the change before it landed.
The solo-project review step is the one I want to spend the most time on, because that's where the rule looks most like theater and is most valuable.
The solo case is the hardest case
When you're alone on a project, the PR step has no second reviewer. You open the PR, you read it yourself, you merge it. Why bother?
Because the PR is the place you write the change down twice. The first write is the commit, the actual diff, the code change. The second write is the PR description, what the change does, why you made it, what you considered and rejected, what could go wrong. The PR description is for your future self, who will read this code in six months, in eighteen months, in three years, and want to know what was going through your head.
I have an active homelab project. Helix, the small AI cluster I run at home. It runs on three boxes I named engine-01, core-01, and store-01. I am the only engineer on it. Every change to the Helix infrastructure repo goes through a PR. The reviewer is me, the merge is me, and the CI is me running pre-commit hooks locally. The discipline is the rule.
The dividend has come every single time I've gone back to a Helm values change from six months earlier and asked myself "what was I trying to do here?" The PR description tells me. The commit alone wouldn't. The diff is what changed; the description is why. The commit message is sometimes enough; the PR description is the place I make myself slow down and write the why properly because the act of opening a PR demands it.
The version of me from six months ago and the version of me today are different engineers. The PR is the handoff between them.
The PR description is the artifact that survives
Five years from now, the diff in the commit history will still be there. The conversation in Slack about why you made the change will not. The decision document in Notion may not. The Linear ticket might be archived. The thing that survives is the PR description in the version control system, attached forever to the commit it produced.
The PR description should answer four questions, in roughly this order: 1. What does this change do? One paragraph, plain language. 2. Why are we doing it now? What problem prompted it, what changed. 3. What did you consider and reject? The roads not taken matter. The fact that you considered making the change differently and chose this path tells the future reader something the diff cannot. 4. What could go wrong? What you tested, what you didn't test, what blast radius this change has, what the rollback looks like.
You'll write a worse version than this most of the time. Even a worse version is better than nothing. The discipline isn't about hitting a writing standard; the discipline is about not letting yourself land code that has no narrative attached.
The PR description is the audit trail
In any environment with a compliance overlay (SOX, SOC 2, HIPAA, anything) auditors are going to ask you to demonstrate that production changes were reviewed before they were applied. PR-only with branch protection is the lowest-friction answer to that question. Every change to production code went through a PR. Every PR has a description, a diff, an approval, and a CI status. The audit trail is the version control system; you don't have to build it, you just have to live the discipline.
This pairs cleanly with the Decisions as Code shape. The PR is the record of every business decision that landed in code: the centralized standards file changed; here's the PR; here's who approved it; here's what they discussed; here's the date it merged. When the auditor asks how a particular policy got changed, the answer is a single URL.
What enforcement looks like
The rule needs teeth or it dies. The teeth are branch protection on main, configured to:
- Require at least one approving review before merge.
- Require all CI checks to pass.
- Require the branch to be up to date with main before merging (so you can't merge a stale branch over fresher work).
- Disallow direct pushes to main, including from administrators.
The "including from administrators" part is non-negotiable. The moment you carve out an exception for the lead engineer, the rule erodes. The lead engineer is the one with the most context and the least supervision; if anyone needs the discipline, it's them.
For solo projects where there's no second human to approve, you can either dial down the review requirement to zero (and rely on the discipline of writing the PR description), or you can use a bot reviewer that checks for things like CI passing, conventional commit format, PR description filled in. The bot isn't doing meaningful review, but it's enforcing the structure of the process.
What you give up
You give up the ability to push a quick fix and move on. That's it. That's the whole list of things you give up.
The cost is roughly thirty seconds to two minutes per change for the friction of the PR process. The dividend is a codebase you can still read in eighteen months, an audit trail that maps every production change to a reviewable artifact, and a forced moment of "is this actually right?" before code lands in main.
I have never regretted requiring PR-only on a project. I have, multiple times, regretted not requiring it.
Article 1 was that the main branch is sacred. Article 2 is that the only way you keep it sacred is by refusing to let anything touch it without going through a PR first. The two articles are different sentences for the same discipline.
, Sid