Comments, Suggestions, and Requesting Review
A review is a batch, not a stream of notifications, and the three buttons at the end of one are a promise about what happens next. Leave a line comment, turn it into a commit the author can accept, and learn what resolving a thread claims.
Worth reading first: The Pull Request, From Branch to Button
A review is a batch, not a stream of notifications, and the three buttons at the end of one are a promise about what happens next. Leave a line comment, turn it into a commit the author can accept, and learn what resolving a thread claims.
A review is a batch, not one comment at a time
On the Files changed tab, hovering over a line shows a blue plus. Click it and you get a comment box with two buttons, and the difference between them is the most useful thing in this chapter.
Add single comment
Posts immediately. The author gets a notification now. Do this eleven times and you have sent eleven notifications, and the author starts fixing the first one before you have found the real problem on line 340.
Start a review
Holds the comment as pending — only you can see it. Keep adding, revise, delete the ones that answered themselves, then submit the whole set at once as one notification with a verdict attached.
Almost always use the second. It is better for the author, who gets a coherent set of feedback rather than a drip. It is also better for you: half the comments you write early in a review turn out to be answered further down, and a pending review lets you quietly delete them instead of posting a correction.
$ gh pr review 483 --comment --body "Looks good, two small things inline"$ gh pr review 483 --approve$ gh pr review 483 --request-changes --body "The export still drops newlines" # Read it locally, which is often faster than the web diff$ gh pr checkout 483$ git diff main...HEADApprove, comment, and request changes mean three things
Submitting a review makes you pick one of three, and they are not interchangeable — they have mechanical consequences, not just tone.
"This can merge." Counts towards a required approval. Say it even with minor comments attached — trusting somebody to fix a nit without re-reviewing is normal and keeps things moving.
Feedback with no verdict. Neither unblocks nor blocks. Right for a question, for a partial review, or for a repository you do not own.
"Do not merge yet." On a protected branch this is a hard block that only you can lift — pushing a fix does not clear it. Use it when something is genuinely wrong, not for a preference.
The other half of the etiquette is how a comment reads. The same technical point can be a collaboration or a verdict, and the difference is mostly grammar.
Lands well
"What happens here if items is empty?"
"Could we pull this into a helper? It is the third copy."
"nit: spelling. Not blocking."
"I did not know about this API — nice."
Costs you something
"This is wrong."
"Why would you do it this way?"
"Obviously this should be a map."
"Did you even test this?"
Two conventions worth adopting because they carry real information. nit: marks a comment as non-blocking taste, so the author knows they may ignore it. And praising something specific is not politeness — it tells the author which decisions to repeat, which is the half of review that never gets written down.
A suggested change is a commit in one click
Instead of describing an edit, write it. A fenced block tagged suggestion in a line comment renders as a proposed diff with a button.
```suggestion if (!res.ok) throw new Error(`loadUser ${id}: ${res.status}`);```src/lib/users.ts
12 export async function loadUser(id) { 13 + const res = await fetch(`/api/users/${id}`); 14 + return res.json(); 15 }fetch does not reject on a 404 — it resolves with ok: false. As written, a missing user parses an error page as JSON and fails somewhere much less obvious. Worth checking here:
Suggested change
if (!res.ok) throw new Error(`loadUser ${id}: ${res.status}`);The author sees a button, not an instruction. That is the whole advantage of a suggestion over “you should check res.ok here” — no retyping, no misreading, and no round trip.
Press the button and it becomes a real commit on the branch, authored by the pull request author with you recorded as co-author. Checks re-run. The thread becomes resolvable.
- 1Multi-line suggestions work
Click the line number and drag to select a range before commenting, and the suggestion replaces the whole range.
- 2Batch them
"Add suggestion to batch" collects several and commits them all as one commit, rather than one commit per typo.
- 3The indentation is literal
Whatever whitespace you type is what lands in the file. A suggestion that drops two spaces of indentation breaks the code.
Resolving a conversation is a claim, so make it true
Every comment thread on the diff has a Resolve conversation button, which collapses it and marks it handled. It is the mechanism a long review uses to stay readable — twenty threads collapse to the three still open.
It is also a claim, and the etiquette around who presses it is a genuine source of friction.
Resolve after making the change, ideally replying with the commit that did it. Resolving without addressing it hides the comment, and reviewers notice.
Resolve when the answer satisfies you. Some teams reserve resolution to the reviewer entirely, which is a defensible rule if it is written down.
Reply before resolving. "Fixed in a1b2c3d" or "Good point, left as is because…" takes five seconds and prevents the whole argument.
Threads on a specific line have a second behaviour worth knowing: outdated. Push a commit that changes the line a comment was anchored to and GitHub hides the thread as outdated. The comment is not gone and not resolved — it is collapsed, and it is very easy for a real objection to disappear this way without anybody deciding it was answered.
Requesting a review is how work reaches a person
A pull request nobody was asked to review is a pull request nobody reviews. Requesting a review puts it in a named person's queue — their Review requested filter, which is what most people actually work from.
$ gh pr create --reviewer alice,bob$ gh pr edit 483 --add-reviewer carol$ gh pr list --search "review-requested:@me" # your actual queueYou can request a team as well as a person, and GitHub will optionally assign a subset by round robin or by load, so the request lands on somebody specific rather than on a group everybody assumes somebody else will handle.
The automatic version is CODEOWNERS — a file mapping path patterns to people or teams. Anyone opening a pull request that touches those paths gets those reviewers requested for them, without having to know who owns what.
# Later rules win, so put the general ones first. * @org/maintainers/src/auth/ @org/security/src/billing/ @alice @org/payments*.sql @org/data/.github/workflows/ @org/platformCombined with branch protection's "Require review from Code Owners", this becomes enforcement: a change to the auth directory cannot merge without somebody from the security team, no matter who approved it. That is how a large repository stays safe without a human router in the middle.
Reviewing well, in one list
- ✓Start a review rather than posting single comments, and submit once
- ✓Read the description first — it tells you what the author was trying to do
- ✓Check the pull request out and run it for anything non-trivial
- ✓Ask questions rather than issuing verdicts; the author usually knows something you do not
- ✓Use suggestions for the small certain fixes and prose for everything else
- ✓Mark taste as "nit:" so it is clearly not blocking
- ✓Say what is good, specifically. It is the only feedback that tells somebody what to repeat
- ✓Reserve "request changes" for genuinely wrong, and dismiss it promptly once it is fixed
- ✓Review quickly. A day of waiting costs the author more than the review costs you
Key takeaways
- "Start a review" holds comments as pending; submit once, as a coherent batch with a verdict.
- Approve counts towards required approvals; Comment is neutral; Request changes is a hard block only that reviewer can lift.
- A blocking review from somebody who then disappears stops the pull request entirely. Do not use it for preferences.
- gh pr checkout fetches the branch, including from a fork, so you can run the code.
- A ```suggestion block becomes a real commit the author accepts with one button.
- Suggestions carry literal indentation and suit small certain fixes; describe anything needing judgement.
- Resolving a conversation is a claim that it is handled. Reply with what you did before resolving.
- Editing a commented line marks the thread outdated and collapses it — real objections vanish this way.
- Pushing a fix notifies nobody. Re-request review explicitly.
- CODEOWNERS requests the right reviewers automatically, and with branch protection it becomes enforcement.
Quick check
Answer these to unlock the next chapter — 3 of 4 to pass. You can retake it anytime.
Answer every question to check.
Make a free account to read on
Every chapter is free — an account is how your progress, XP, and streak follow you from your laptop to your phone, and how you show up on the leaderboard. No payment, no trial.