Skip to content

Cheatsheet: Pull requests

Git stores snapshots. Every other command is just navigating those snapshots.

A pull request is a proposal to merge one set of snapshots into another.

Terminal window
# 1. Branch (assumes L5)
git switch -c feature/payment-flow
# 2. Do the work; commit with discipline (L3)
git add .
git commit -m "feat(checkout): add stripe integration"
# 3. Push the branch (-u sets upstream for future pushes)
git push -u origin feature/payment-flow
# 4. Open PR on the platform UI
# 5. Write the description (next section)
# 6. Request reviewers
# 7. Address comments (push more commits to same branch)
git add fix.ts
git commit -m "address review: handle null case"
git push
# 8. Merge via UI (pick a strategy)
# 9. Delete the branch (button in UI after merge)
## What this changes
Brief description of what the diff does. One paragraph. Bullets if multiple distinct changes.
## Why this matters
The motivation. What problem this solves. Link to ticket / design doc / customer report.
## How it was tested
What you ran, what you observed. Manual steps if applicable. Test coverage if added.
## Notes for the reviewer
Tradeoffs considered. Alternatives ruled out. Things you're unsure about. Pre-empts reviewer questions.

Optional sections (add when relevant):

## Screenshots / videos
For UI changes.
## Breaking changes
For API or schema changes.
## Migration plan
For schema migrations or coordinated deploys.
## Rollback plan
For anything risky.
If…Choose
Branch has messy WIP commitsSquash
Branch represents a discrete unit and history mattersMerge commit
Branch has clean commits AND team wants linear historyRebase
You don’t have a team default yetSquash (safest starter)
PrefixMeaningAuthor response
nit:Style preference, not blockingOptional, fix or skip
suggestion:Consider thisOptional, engage or skip
question:Asking for clarificationRequired, answer it
blocking:Must address before mergeRequired, fix or push back

If you don’t use prefixes, comments are ambiguous. Pick a convention; document in CONTRIBUTING.md.

  • Read your own diff before requesting review
  • Run tests locally
  • Self-review with explanatory comments
  • Respond to every comment (even “fixed in <sha>”)
  • Push fixes as new commits, don’t force-push during review
  • Disagree with explanation, not silence
  • Escalate to synchronous after 2-3 async rounds of disagreement
  • Within 1 business day for normal PRs, hours for urgent
  • Review the code, not the person
  • Be specific (“consider X for reason Y”) not vague (“this isn’t great”)
  • Tag blocking vs non-blocking
  • Approve when good enough, not perfect
  • If you can’t approve, say what would unblock approval
  1. Mega-PR: break into logical units (200-300 line sweet spot)
  2. Unrelated changes PR: one logical change per PR
  3. No description PR: spend three minutes on description
  4. Scope-drifted PR: update description as scope changes
  5. Generated code in diff: separate generated artifacts
  6. No tests: tests with the code, same PR
  7. Friday 5pm PR: time PRs for when you can engage with review
  8. Self-merge bypass: if review is being skipped routinely, the team has a process gap

Drill 4 model rewrites, review comment fixes

Section titled “Drill 4 model rewrites, review comment fixes”
  1. “This is wrong.” becomes “This case crashes when input is null; can we add a null check or assert upstream?”
  2. “Why didn’t you use the existing helper?” becomes “We have a parseUser() helper in lib/auth.ts that handles the same case. Worth using for consistency, unless there’s a reason this needs to be custom?”
  3. “lgtm” becomes “Looks good, clean separation of concerns, tests cover the happy path and edge cases I’d worry about. Approving.”
  4. “Can we just not do this?” becomes “I’m hesitant about adding this feature because [specific reason]. Could we discuss the framing in a quick sync before committing to this approach?”
  5. “Did you test this?” becomes “What testing did you do? I don’t see new test cases in the diff; if it’s covered elsewhere, can you link?”
  1. “This variable name is misleading; rename to userIds.” Answer: nit (style; not load-bearing)
  2. “Doesn’t handle null input; will crash in production.” Answer: blocking (correctness)
  3. “Prefer trailing commas.” Answer: nit (style; should be lint-enforced)
  4. “SQL injection vector.” Answer: blocking (security)
  5. “Consider extracting this into a helper.” Answer: suggestion (structural; optional)

L7 covers merge conflicts: what happens when two branches modify the same lines, and how to resolve calmly. The PR loop from L6 continues to work; you just add a conflict-resolution step before merge. The mental model is unchanged (snapshots, navigation, labels); conflicts are just git asking “you have two snapshots that disagree on this line; which do you want?”