Code review is where a pull request does most of its work. It is not just a quality gate — it is a conversation. The review process is where bugs get caught, design decisions get questioned, knowledge gets shared, and the final shape of a change gets worked out collaboratively. Understanding how to both give and receive code review effectively is one of the most valuable skills in collaborative software development.
The Pull Request Page
Once a PR is open, its page becomes the central hub for all activity. It has four key tabs:
| Tab | What It Shows |
|---|---|
| Conversation | The main discussion thread — general comments, review summaries, and the activity timeline |
| Commits | All commits on the branch, in order |
| Checks | Results of automated status checks — CI tests, linting, security scans |
| Files changed | The unified diff of all changes the PR would introduce if merged |
The Files changed tab is where most code review happens. It shows the aggregate diff — every line added, removed, or modified across all commits — exactly as it would appear after merging.
How GitHub Displays Diffs
In the Files changed tab, GitHub displays a unified diff for each file:
- Lines prefixed with
+(green) are additions. - Lines prefixed with
-(red) are removals. - Unchanged lines provide context.
You can switch between unified diff (additions and removals interleaved) and split diff (two columns, before and after) using the toggle at the top of the Files changed tab. Split view is often easier to read for complex changes.
Leaving Comments as a Reviewer
Line-level comments
To comment on a specific line, hover over it in the Files changed tab — a blue + button appears on the left. Click it to open a comment box anchored to that exact line. Line-level comments are the most precise form of review feedback — they make it unambiguous exactly what the reviewer is referring to.
You can also click and drag across multiple lines to anchor a comment to a range of lines rather than a single one.
Suggesting changes
Rather than describing what should change in words, GitHub lets reviewers suggest a specific replacement directly in the comment using a suggestion code block:
```suggestion
const timeout = 3000;
```
This renders as a formatted diff showing the proposed change. The author can apply the suggestion with a single click — GitHub automatically creates a commit with the change. This is particularly useful for small, unambiguous fixes like typos, variable naming, or formatting.
General comments
Comments on the Conversation tab apply to the PR as a whole rather than to a specific line. These are used for high-level feedback — architecture concerns, questions about the overall approach, or anything that does not attach neatly to a single line of code.
Submitting a Formal Review
Rather than posting individual comments one at a time (which each trigger a notification), GitHub lets reviewers batch their feedback into a single review submission. This is the standard practice — it is less noisy for the author and presents the feedback as a coherent whole.
To start a review:
- Go to the Files changed tab.
- Click the
+button on any line to add a comment. - Click Start a review (instead of Add single comment).
- Continue adding comments to other lines — they are held in a pending state, not yet posted.
- When finished, click Finish your review (or Review changes at the top right).
- Write an overall summary comment.
- Choose one of three review outcomes:
| Outcome | Meaning |
|---|---|
| Comment | Submits feedback without explicitly approving or requesting changes. Used for questions or minor observations. |
| Approve | The changes look good. The reviewer is satisfied and the PR can be merged (pending any other requirements). |
| Request changes | The reviewer has concerns that must be addressed before merging. The PR is blocked until the reviewer dismisses their review or re-reviews. |
After submitting, all held comments are posted together and the author receives a single notification.
Responding to Review Feedback as the Author
Making changes
Respond to review feedback by making changes to your branch and pushing:
# Make the requested change
git add src/settings.js
git commit -m "Use const for timeout variable as suggested"
git push origin feature/dark-mode
The pull request updates automatically — the new commit appears in the timeline and in the Commits tab. Addressed review comments are visually collapsed in the Files changed view once the relevant lines have been updated.
Note: Pushing additional commits to a PR does not automatically trigger a new notification to the reviewer. It is good practice to leave a comment on the PR letting reviewers know the feedback has been addressed — especially if multiple changes were requested.
Resolving conversations
Once a comment thread has been addressed, either the author or the reviewer can click Resolve conversation to collapse it. Resolved conversations are hidden by default but can be expanded again. A PR is generally ready to re-review once all conversations are resolved.
Responding without changing code
Not every review comment requires a code change. Sometimes the right response is to explain why the current approach was chosen:
- Answer the question directly in the comment thread.
- If the reviewer still disagrees, the discussion continues until consensus is reached.
- If the change is genuinely a matter of preference, the maintainer makes the call.
Disagreements in code review are normal. The goal is to reach the best outcome for the codebase, not to win arguments. Keep discussion focused on the code, not on personalities.
Keeping the PR Up to Date with Main
If main has advanced since the PR was opened — new commits were merged by other contributors — the PR branch may fall behind. GitHub indicates this at the bottom of the Conversation tab:
This branch is out-of-date with the base branch.
Update the branch by merging in the latest main:
git switch feature/dark-mode
git fetch origin
git merge origin/main
# Resolve any conflicts
git push origin feature/dark-mode
Or, if you prefer a linear history, rebase:
git rebase origin/main
git push --force-with-lease origin feature/dark-mode
Use
--force-with-leaseinstead of--force.--force-with-leaserefuses to push if the remote branch has been updated since your last fetch — protecting against accidentally overwriting a collaborator's commits.
GitHub also provides an Update branch button at the bottom of the PR page for simple cases where there are no conflicts — it performs the merge on GitHub's servers without requiring any local commands.
Status Checks
Many repositories have automated status checks configured — tests, linters, security scans — that run every time a commit is pushed to the branch. These appear in the Checks tab and in the merge section at the bottom of the PR page.
Status check states:
| State | Meaning |
|---|---|
| ✅ Passing | All checks passed |
| ❌ Failing | One or more checks failed — merging is typically blocked |
| 🔄 Pending | Checks are still running |
If checks are failing, the author is expected to fix the issues before requesting re-review. Clicking on a failing check shows the full log output, which usually makes the problem clear.
The Review Cycle
A pull request often goes through multiple rounds of review before merging:
Author opens PR
↓
Reviewer leaves feedback
↓
Author addresses feedback and pushes
↓
Author notifies reviewer
↓
Reviewer re-reviews
↓
┌─ More feedback → back to author
└─ Approved → ready to merge
In practice, well-scoped pull requests with clear descriptions often need only one round of review. Larger, more complex PRs may go through several cycles. This is not a failure — it is the process working correctly.
Giving Good Code Review
Code review is a skill that takes time to develop. Some principles that make reviews more effective:
- Be specific. "This function is confusing" is less useful than "This function handles three different concerns — consider splitting it."
- Explain why. "Use
consthere because this value is never reassigned — it signals intent to future readers." - Distinguish must-fix from nice-to-have. Prefix non-blocking suggestions with "Nit:" or "Optional:" so the author knows what is required vs. what is a preference.
- Ask questions instead of making demands. "What was the reasoning for this approach?" opens a dialogue. "This is wrong" closes it.
- Review the intent, not just the code. Does the change actually solve the problem it claims to solve?
- Acknowledge what is done well. Positive feedback is as valuable as critical feedback — it tells the author what to keep doing.
Summary
| Action | How to do it |
|---|---|
| Comment on a specific line | Hover over the line in Files changed, click + |
| Suggest a specific change | Use a suggestion code block in a comment |
| Submit a batched review | Files changed → Start a review → Finish your review |
| Approve a PR | Finish review → Approve |
| Request changes | Finish review → Request changes |
| Address feedback | Commit changes to the branch and push |
| Notify reviewer of updates | Leave a comment on the PR |
| Resolve a comment thread | Click Resolve conversation |
| Update branch with main | git merge origin/main or use the Update branch button |