A pull request is the unit of collaboration: a diff, a discussion, a CI result and a decision. Writing and reviewing them well is a skill hiring teams notice immediately.
Learning objectives
- Open a pull request that a reviewer can understand in minutes.
- Review code for correctness, clarity and risk.
- Use squash merging without losing context.
- Configure branch protection and required checks.
1. Before opening the PR
git switch main && git pull --ff-only
git switch feature/course-filters
git rebase main
npm test
git push -u origin feature/course-filters
A PR that does not build wastes the reviewer's first ten minutes.
2. Writing the description
## What
Adds level and mode filters to the course catalogue.
## Why
Visitors currently scroll through 40 courses. Filtering reduces time to
course selection and matches the filters already used on /locations.
## How
- URL state via `useSearchParams` (shareable links)
- Filtering happens client-side; the catalogue is 40 items
- Empty state added when no course matches
## Testing
- `npm test` — 42 passing
- Manual: /courses?level=beginner&mode=online
- Checked mobile at 360px
## Screenshots
(before / after)
The reviewer should not have to reconstruct the intent from the diff.
3. Keep the diff reviewable
- Under ~400 changed lines is comfortable; 1,500 is a rubber stamp.
- Separate refactors from behaviour changes.
- Do not mix formatting with logic.
- Delete dead code in its own commit.
- Link the issue the PR closes:
Closes #128.
4. Reviewing
Review in this order:
- Does it do what it claims? Read the description, then the tests.
- Correctness — edge cases, error paths, empty states, permissions.
- Security — user input, secrets, authorisation checks.
- Clarity — names, structure, comments where the "why" is non-obvious.
- Style — let the formatter and linter handle it; do not argue taste in review.
Comment types:
- Blocking: "This allows an unauthenticated user to delete a course."
- Question: "What happens when
itemsis empty?" - Suggestion: "Could this reuse
formatPricefrom lib/money?" - Nit: "Typo:
recieve→receive." — mark as non-blocking.
Approve when the change is safe to ship, not when it is perfect.
5. Responding to review
- Push follow-up commits; do not force-push during an active review unless the team expects it.
- Reply to every comment — "Done in abc123" or a reason.
- If you disagree, explain the constraint and propose an alternative.
- Resolve conversations only after the reviewer confirms.
6. Merging
Merge commit keeps every commit and the branch shape. Squash and merge turns the PR into one commit on main:
Add course filters (#128)
Squash is the default for most product teams: one logical change, one revertable commit, a clean main. Use merge commits when preserving the individual commits matters.
After merging:
git switch main
git pull --ff-only
git branch -d feature/course-filters
7. Branch protection
On GitHub: require a pull request before merging, require approvals, require status checks, require branches to be up to date, disallow force pushes. These settings turn good intentions into guarantees.
Common mistakes
- A PR titled "fixes" with no description.
- Reviewing 2,000 lines and approving because it is too late to read.
- Force-pushing while reviewers are mid-review.
- Merging with failing tests "to unblock" — that is how
mainbecomes undeployable. - Leaving the branch undeleted and the issue open.
Practice
Complete the review exercise in the assignment: open a small PR, review someone else's, and merge with a squash commit.