Efficient Code Review Workflow in GitLab: Using Diffs, Suggestions, and Threads
AI generated
CI/CD
.yml
GitLab · Code Review · Productivity
Efficient Code Review Workflow
Mastering diffs, suggestions, and threads

A good code review workflow in GitLab does not rely on good intentions but on the right tools: applicable suggestions, cleanly resolved discussion threads, and strategies to review even large diffs in a reasonable amount of time.

16 min read Suggestions Diff Navigation Review Threads

1. Why review time often exceeds the time spent coding

In many teams, code review eats up more time than writing the code itself, not because the changes are complex, but because the workflow around the review is inefficient. Reviewers jump back and forth between comments, authors have to manually transfer every suggestion into their local environment, and unresolved discussions pile up until nobody is quite sure anymore which ones are still open and which are actually done.

GitLab offers concrete tools for exactly these friction points: suggestions that can be applied with a single click, a diff view with several comparison modes, and a thread system that distinguishes between "resolved" and "archived". Teams that know these tools and use them consistently can noticeably reduce the average review duration of a merge request without sacrificing the substance of the review.

2. Suggestions: making proposals directly applicable

A comment like "a null check is missing here" forces the author to reload the context, make the change locally, and produce a new commit. With the suggestion feature, the reviewer instead formulates the proposed code directly in the diff, which the author can adopt with a click on "Apply suggestion". GitLab automatically generates a commit from it without the author having to open their IDE. For small, unambiguous changes like typos, missing type hints, or an incorrect variable name, this saves considerable time on both sides.

Suggestions can also be used for multi-line changes by having the reviewer select a line range in the diff and formulating the suggestion across multiple lines. The workflow becomes even more efficient when several related suggestions are collected in a batch and applied together via "Apply suggestions", producing a single commit instead of many small individual ones and keeping the commit history clean.


```suggestion
if ($product === null) {
    throw new NoSuchEntityException(__('Product not found.'));
}
```
# This block is inserted directly in the GitLab comment field
# above the affected diff region and, when applied, replaces
# exactly the highlighted lines in the target branch.

3. Choosing the right diff view for the situation

GitLab offers several diff presentations that are helpful in different ways depending on the situation. The inline diff works well for small, localized changes, while the side-by-side view makes direct comparison between old and new code easier for larger refactorings. Also important is the option to hide whitespace changes, which is especially useful after automatic formatting runs (for example via PHP-CS-Fixer or Prettier) to separate the actual content diff from pure formatting noise.

For merge requests based on an older base commit, the Compare with target branch view helps check whether intervening changes to the target branch create conflicts or unexpected side effects. An often-overlooked feature is also the ability to restrict a diff to a specific commit range, which for merge requests with many small intermediate commits focuses the review on the actual new changes since the last review pass instead of re-checking the entire diff.

4. Resolving threads: when and how

A discussion thread in GitLab is marked as "resolved" once the raised question is clarified or the requested change has been implemented. It matters as a team convention who is allowed to resolve the thread: it has proven effective for the reviewer who opened the discussion to be the one who resolves it, not the author. This prevents an author from silently marking a critical remark as done without the reviewer actually confirming the implementation.

GitLab lets you configure the merge button to become active only once all threads are resolved (Settings > Merge requests > All threads must be resolved). This setting is especially valuable because it prevents an open but unanswered discussion from simply getting lost in the chaos of a hectic sprint while the merge request still gets merged.

5. Resolving versus archiving: the important distinction

A common misunderstanding is equating "resolving" with "archiving". Resolving a thread signals in substance that a concrete problem has been fixed and remains visibly documented in the merge request. When a merge request is closed or merged, the entire discussion can optionally be considered concluded without manually resolving every single thread, which is practical for merge requests with many minor side discussions.

For general remarks that do not require a change, such as praise for an elegant solution or a question out of pure interest, there should be no obligation to resolve. It works well to clearly mark such comments as "non-blocking", for example with the prefix nit: for minor issues or question: for pure understanding questions, so both author and reviewer can see at a glance which comments actually block the merge.

6. Strategies for large, unwieldy diffs

A merge request with several thousand changed lines is the biggest time trap in the review process, because no human can reliably hold that amount of context in their head. The most effective measure is preventive: keep merge requests small from the start, ideally under 400 changed lines, and split larger refactorings into several successive merge requests. Where that is not possible for functional reasons, it helps to mark generated files (lockfiles, compiled assets, automatically formatted code) with linguist-generated via .gitattributes so GitLab collapses them in the diff by default.

For truly unavoidable large diffs, a structured multi-pass review pays off: the first pass only checks architecture and data flow, and the second pass covers detail questions about individual functions. GitLab supports this by letting individual files in the diff be marked as "Viewed", which makes progress visible across multiple sessions and prevents already-reviewed files from being fully re-checked on the next login.


# .gitattributes
# Collapse generated/compiled files in the diff by default
package-lock.json     linguist-generated=true
pub/static/**          linguist-generated=true
var/generated/**       linguist-generated=true
*.min.js               linguist-generated=true

7. Using quick actions in review comments

Beyond substantive feedback, GitLab quick actions can be used directly in review comments to trigger status changes without switching views. A comment with /approve approves the merge request, /request_changes explicitly marks it as needing changes, and /assign @developer assigns an open question directly to a specific person. This significantly reduces the number of clicks between the comment field and the merge request header.

Particularly useful in day-to-day review work is /reassign, to clearly hand off responsibility for follow-up work, as well as /label ~needs-tests, to immediately flag missing test coverage on the board. These quick actions can be combined with ordinary free text in the same comment, so the substantive reasoning and the status change happen in a single step.

8. Review etiquette: comments that save time instead of costing it

The wording of review comments has a direct impact on the speed of the whole process. A comment like "this is wrong" usually triggers a follow-up question and thus an extra round of iteration, while "this causes a division by zero on an empty cart, see line 42" is immediately actionable. Clear, well-reasoned comments with a concrete reference measurably reduce the number of back-and-forth rounds between author and reviewer.

Just as important is a realistic expectation for response time: a team standard like "first review within four hours during core working hours" prevents merge requests from sitting for days while the author loses context in the meantime. GitLab supports this through notification rules and the ability to explicitly assign reviewers rather than only assignees, which in many teams leads to noticeably faster response times.

9. Measuring review time and optimizing deliberately

Without measurement, every optimization remains a guess. Through the Value Stream Analytics feature, GitLab provides metrics such as the average time from opening a merge request to the first review and to the final merge. Tracking these numbers across several sprints objectively shows whether measures like smaller merge requests or a new review rotation plan actually work, instead of relying on individual team members' subjective impressions.

It is also worth looking at how reviews are distributed across the team: if all reviews pile up on one or two experienced people, a bottleneck forms that becomes immediately noticeable when they are absent. Deliberate rotation, supported by the CODEOWNERS group mapping, distributes the load more evenly and simultaneously builds knowledge across the whole team instead of concentrating it in a few people. The table below summarizes the key tools and the time savings each one provides.

Tool Solves which problem Saves time for Location in GitLab
Suggestions Manually transferring small fixes Author Diff comment field
Batch suggestions Many individual commits for small fixes Author Review sidebar
Hide whitespace Formatting noise in the diff Reviewer Diff view, filter icon
Viewed marker Repeatedly checking already-seen files Reviewer Diff file tree
All threads must be resolved Overlooked open discussions Whole team Settings > Merge requests

Mironsoft

CI/CD pipelines, zero-downtime deployments and release automation

Deployments that run without downtime and without the nail-biting?

We review existing GitLab pipelines for fragile deployment steps and missing safeguards, then build a release process with zero-downtime deployments, automated checks and a rollback you can actually trust in an emergency.

Pipeline Review

Checking an existing .gitlab-ci.yml for fragility, missing stages and security gaps.

Zero-Downtime Deployment

Building symlink releases, health checks and rollback strategies for Magento stores.

CI/CD Automation

Connecting tests, security scans and deployments into one reliable pipeline.

10. Summary

Code Review Workflow: The Essentials at a Glance

Suggestions

Make proposals directly applicable instead of manually transferring changes.

Thread discipline

Resolved by the reviewer, archived only on merge or closure.

Small diffs

Keep merge requests small preventively rather than speeding up reviews after the fact.

Measurement

Value Stream Analytics shows whether optimizations actually work.

11. FAQ: Code Review Workflow: The Essentials at a Glance

1How do I apply several suggestions at once?
In the review view, several suggestions can be selected via the batch feature and then applied together as a single commit via 'Apply suggestions', instead of generating a separate commit for each suggestion.
2Can I reopen a thread that has already been resolved?
Yes, any user with sufficient permissions can reopen a resolved thread via the 'Unresolve' button, for example when closer inspection reveals that the original problem was not fully fixed after all.
3What happens to open threads when a merge request is merged?
Open threads remain visible after the merge and are not automatically resolved. If 'All threads must be resolved' is enabled, it prevents the merge in the first place as long as threads are open.
4How do I prevent formatting changes from obscuring the real diff?
Enable the whitespace filter in the diff view for the review session, and permanently mark generated or automatically formatted files with linguist-generated in the .gitattributes file.
5Is the viewed marker per user or visible to everyone?
The viewed marker is per person. Each reviewer only sees their own progress, so multiple reviewers can navigate through the same diff independently without affecting each other.
6How large should a merge request be at most?
There is no fixed limit, but experience suggests 200 to 400 changed lines as a practical maximum, beyond which review quality noticeably drops in studies and practical reports.
7Can I use quick actions in a single diff comment instead of the main comment field?
Yes, quick actions work both in the merge request's general comment field and in a comment on a single diff line.
8How do I handle discussions that do not require a change?
Such comments should be clearly marked as non-blocking, for example with a prefix like 'nit:' for minor issues, and can then be resolved or left open independently of merge progress.
9Does Value Stream Analytics also show individual reviewer statistics?
Value Stream Analytics primarily focuses on process times for the whole team and project. For individual reviewer distribution, it is also worth looking at merge request analytics or building a custom API-based evaluation of approval data.
10Is a multi-pass review worthwhile for every large merge request?
Not for every one, but for merge requests with significant architectural changes, a two-stage approach, first structure, then details, is usually faster and more thorough than a single monolithic review pass.