<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pyor</title>
    <description>The latest articles on DEV Community by Pyor (pyor).</description>
    <link>https://dev.to/pyor</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F13903%2F44c40a22-0c32-45f2-8583-e9d15712826d.png</url>
      <title>DEV Community: Pyor</title>
      <link>https://dev.to/pyor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pyor"/>
    <language>en</language>
    <item>
      <title>What Is a Merge Queue and Why Do Teams Use One?</title>
      <dc:creator>Othman Shareef</dc:creator>
      <pubDate>Tue, 20 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/pyor/what-is-a-merge-queue-and-why-do-teams-use-one-4onn</link>
      <guid>https://dev.to/pyor/what-is-a-merge-queue-and-why-do-teams-use-one-4onn</guid>
      <description>&lt;p&gt;A merge queue is an automated system that merges pull requests one group at a time, testing each against the latest state of the target branch first, so changes that pass CI in isolation cannot break the branch when combined.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The short answer:&lt;/strong&gt; What is a merge queue buying you? Certainty that green means green. Instead of trusting checks that ran against an old version of main, the queue builds the merge result that would actually land, runs CI on that, and only then merges. GitHub describes it as automating merges into a busy branch while ensuring the branch is never broken by incompatible changes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What problem does a merge queue solve?
&lt;/h2&gt;

&lt;p&gt;The stale-CI problem. Your pull request passed its checks, but it passed them against the main branch as it existed when CI last ran. By the time you press merge, five other pull requests have landed. Git may combine everything without a textual conflict and still produce a broken result: your change calls a function someone else just renamed, or relies on behavior another merge removed. Nothing in branch protection catches this, because each change was green on its own. The manual fix is updating your branch and re-running CI before merging, but on a busy repository that becomes a race: by the time your re-run finishes, main has moved again. Teams end up with developers babysitting the merge button, or with a main branch that breaks weekly for reasons no single PR caused.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a merge queue doing under the hood?
&lt;/h2&gt;

&lt;p&gt;Instead of merging immediately, an approved and green pull request is added to a queue. From there, per &lt;a href="https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue" rel="noopener noreferrer"&gt;the GitHub merge queue docs&lt;/a&gt;, the process looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The queue creates a temporary branch containing the speculative merge result: the latest target branch, plus the queued pull request, plus any pull requests ahead of it in line.&lt;/li&gt;
&lt;li&gt;Required CI checks run against that merge group, not against the stale branch.&lt;/li&gt;
&lt;li&gt;Pull requests merge in first-in-first-out order, each only after its group passes.&lt;/li&gt;
&lt;li&gt;If a group fails, the failing pull request is removed from the queue and the speculative merges behind it are rebuilt without it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Batching is the efficiency trick: by testing several queued pull requests together in one merge group, the queue validates many changes with one CI run and keeps throughput high even when each run takes twenty minutes. Batch size and merge method are configurable per repository, so teams can tune throughput against CI cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who needs a merge queue?
&lt;/h2&gt;

&lt;p&gt;The queue earns its complexity in proportion to merge traffic. Signals that you have crossed the line: developers regularly click update branch two or three times before a merge sticks, main breaks from combinations of individually green changes, or merge order has become something people coordinate in chat. High-traffic monorepos and teams practicing &lt;a href="https://pyor.review/blog/trunk-based-development-code-review" rel="noopener noreferrer"&gt;trunk-based development&lt;/a&gt; hit this earliest, since everyone is landing small changes into the same branch all day. If that is you, our &lt;a href="https://pyor.review/blog/github-merge-queue-explained" rel="noopener noreferrer"&gt;deep dive on the GitHub merge queue&lt;/a&gt; covers setup, CI wiring, and the operational sharp edges.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does a merge queue not do?
&lt;/h2&gt;

&lt;p&gt;A queue automates the last step, not the judgment before it. It does not review code, and it does not loosen &lt;a href="https://pyor.review/blog/github-branch-protection-required-reviews" rel="noopener noreferrer"&gt;required reviews&lt;/a&gt;; a pull request still needs its approvals and passing checks just to enter. It also does not decide that a pull request is ready, which is &lt;a href="https://pyor.review/blog/github-auto-merge" rel="noopener noreferrer"&gt;auto-merge&lt;/a&gt; territory; the two compose nicely, with auto-merge queueing the PR the moment review completes. And it cannot save you from flaky tests: a queue amplifies test unreliability, because one flaky failure now ejects a pull request and re-runs everything behind it. Green must mean green for the queue to mean anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Does a merge queue replace required reviews or CI?
&lt;/h3&gt;

&lt;p&gt;No. It sits after them. A pull request still needs its approvals and passing checks to enter the queue; the queue then re-runs required checks on the speculative merge result. Think of it as a final gate that validates the combination, not the individual change.&lt;/p&gt;

&lt;h3&gt;
  
  
  What happens when a pull request fails in the merge queue?
&lt;/h3&gt;

&lt;p&gt;It is removed from the queue rather than merged, and the queue rebuilds the speculative merges for the pull requests behind it without the failing change. The author fixes the problem and re-queues. Everything else keeps flowing, which is the point of the design.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do small teams need a merge queue?
&lt;/h3&gt;

&lt;p&gt;Usually not. The stale-CI problem grows with merge frequency. A team merging a few pull requests a day can just update branches before merging. Once merges start racing each other daily, or updating branches becomes a full-time chore, a queue starts paying for itself.&lt;/p&gt;

</description>
      <category>github</category>
      <category>codereview</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Graphite vs CodeRabbit for PR Reviews: An Honest Take</title>
      <dc:creator>Othman Shareef</dc:creator>
      <pubDate>Mon, 19 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/pyor/graphite-vs-coderabbit-for-pr-reviews-an-honest-take-23bg</link>
      <guid>https://dev.to/pyor/graphite-vs-coderabbit-for-pr-reviews-an-honest-take-23bg</guid>
      <description>&lt;p&gt;We sell neither Graphite nor CodeRabbit (we build Pyor, a review surface that sits next to both, so read this with that in mind). The two get compared as if they were the same kind of product, but Graphite is a pull request workflow and CodeRabbit is a review bot that joins the workflow you already have. We checked everything below against the vendors’ own pages and one open benchmark in October 2026, and where the sources disagree we say so.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The short answer:&lt;/strong&gt; Graphite and CodeRabbit only overlap on one feature. CodeRabbit is a dedicated AI reviewer that comments on your PRs, on four git hosts, from $24 per developer a month. Graphite is a GitHub workflow platform (stacked PRs, a merge queue, an inbox) that also ships an AI reviewer, with unlimited AI reviews at $40 per user a month. On an open benchmark, CodeRabbit catches far more issues and Graphite stays quieter. Pick CodeRabbit if you want a bot, and Graphite if you want stacking.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What each one is for
&lt;/h2&gt;

&lt;p&gt;Graphite is a pull request workflow platform for GitHub. Its core is stacked pull requests: a CLI and a VS Code extension that let you split a big change into a chain of small dependent PRs without the rebase bookkeeping. Around that sit a stack-aware merge queue, a PR inbox, Slack notifications, team insights, and an AI reviewer. &lt;a href="https://graphite.com/" rel="noopener noreferrer"&gt;Graphite’s homepage&lt;/a&gt; calls it “the AI code review platform”, but what your team adopts is the platform, and the reviewer comes with it.&lt;/p&gt;

&lt;p&gt;CodeRabbit is a dedicated AI review agent. You install it, and it reviews every pull request with line comments, a summary, one-click fixes, and pre-merge checks. Per &lt;a href="https://docs.coderabbit.ai/" rel="noopener noreferrer"&gt;its docs&lt;/a&gt; it runs on GitHub, GitLab, Azure DevOps, and Bitbucket, in VS Code, Cursor, and Windsurf through an extension, and from a CLI before you commit. Your team branches and merges the same way it did before.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI review quality on an open benchmark
&lt;/h2&gt;

&lt;p&gt;Most “benchmarks” you will find for these two are run by a vendor, and the vendor tends to win. The one we trust most is &lt;a href="https://codereview.withmartian.com/" rel="noopener noreferrer"&gt;Martian’s Code Review Bench&lt;/a&gt;, because its &lt;a href="https://github.com/withmartian/code-review-benchmark" rel="noopener noreferrer"&gt;method and code are open source&lt;/a&gt; and Martian runs every tool itself rather than taking submitted results. It has two modes, and both include CodeRabbit and Graphite.&lt;/p&gt;

&lt;p&gt;The offline benchmark uses 50 PRs from five open source projects (Sentry, Grafana, Cal.com, Discourse, and Keycloak) with human-verified “golden” comments, then has an LLM judge match each tool’s comments against them. In the snapshot dated September 8, 2026 (default judge and category profile), CodeRabbit scored 42.2% F1 with 59.5% recall and 32.6% precision. Graphite scored 14.1% F1: it made 12 correct comments and zero wrong ones, for 100% precision, but found only 7.6% of the known issues.&lt;/p&gt;

&lt;p&gt;The live benchmark is the one we weigh more. It samples fresh merged PRs on GitHub where a bot commented, and counts a bot comment as useful when it matches a fix the developer made afterwards. Over December 25, 2025 to October 17, 2026, with the leaderboard’s filters cleared, CodeRabbit sat at 52.2% F1 (54.2% precision, 50.2% recall) across about 48,900 scored PRs. Graphite sat at 41.5% F1 (64.9% precision, 30.6% recall) across about 1,460. You only see Graphite once you clear the default volume filters, since it reviews far fewer public PRs than CodeRabbit does.&lt;/p&gt;

&lt;p&gt;Both modes show the same trade. Graphite’s reviewer says little, and what it says is usually right. CodeRabbit says a lot more and catches a lot more, with more comments that go nowhere. Graphite’s own &lt;a href="https://graphite.com/features/ai-reviews" rel="noopener noreferrer"&gt;AI reviews page&lt;/a&gt; leans into that trade (it claims a negative comment rate under 5% in its own tests, without publishing the method). An older &lt;a href="https://www.greptile.com/benchmarks" rel="noopener noreferrer"&gt;July 2025 test published by Greptile&lt;/a&gt; points the same way (CodeRabbit caught 44% of 50 planted bugs, Graphite 6%), but Greptile sells a competing reviewer and scored itself highest, so weigh it as a vendor claim.&lt;/p&gt;

&lt;p&gt;Precision decides how much of your reviewers’ time the bot burns, and recall decides how much it saves them from missing. We cover why benchmarks disagree in &lt;a href="https://pyor.review/blog/ai-code-review-accuracy" rel="noopener noreferrer"&gt;how accurate AI code review really is&lt;/a&gt;. A two-week trial on your own PRs will tell you more than any of these numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing and free tiers in 2026
&lt;/h2&gt;

&lt;p&gt;As of October 2026, &lt;a href="https://graphite.com/pricing" rel="noopener noreferrer"&gt;Graphite’s pricing page&lt;/a&gt; lists annual prices only, and &lt;a href="https://www.coderabbit.ai/pricing" rel="noopener noreferrer"&gt;CodeRabbit’s&lt;/a&gt; lists annual prices with monthly prices in its FAQ.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Graphite&lt;/th&gt;
&lt;th&gt;CodeRabbit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Hobby: personal repos only, limited AI reviews and chat&lt;/td&gt;
&lt;td&gt;Free reviews on public repos; no free plan for private repos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entry paid tier&lt;/td&gt;
&lt;td&gt;Starter, $20/user/mo billed annually: org repos, AI reviews still limited&lt;/td&gt;
&lt;td&gt;Essentials, $24/dev/mo annual or $30 monthly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unlimited AI review&lt;/td&gt;
&lt;td&gt;Team, $40/user/mo billed annually, which also adds the merge queue&lt;/td&gt;
&lt;td&gt;No total cap; past an hourly per-developer allowance, $0.25 per reviewed file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Higher tiers&lt;/td&gt;
&lt;td&gt;Enterprise, custom&lt;/td&gt;
&lt;td&gt;Team $48 ($60 monthly), Advanced $72, Enterprise custom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trial&lt;/td&gt;
&lt;td&gt;30-day trial&lt;/td&gt;
&lt;td&gt;14-day trial&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For unmetered AI review on private org repos, Graphite starts at $40 a seat and CodeRabbit at $24. Graphite’s $40 also buys the merge queue and stacking workflow, so if you would not use those, you are paying for a platform to get a reviewer. Model CodeRabbit’s usage pricing before you commit: Essentials allows 5 reviews per developer an hour, and continued reviews bill per file, with an admin spending cap to stop surprises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow lock-in and who owns what
&lt;/h2&gt;

&lt;p&gt;CodeRabbit is easy to leave. It is an app on your repos, so when you uninstall it, your PRs, branches, and merge process stay exactly as they were. You lose its configuration and the “learnings” it has collected from your team’s feedback. It also follows you across hosts, which matters if part of the org lives on GitLab or Bitbucket.&lt;/p&gt;

&lt;p&gt;Graphite asks for more commitment, by design. The AI reviewer alone is not sticky: Graphite’s &lt;a href="https://graphite.com/docs/ai-reviews-setup" rel="noopener noreferrer"&gt;setup docs&lt;/a&gt; say it reviews all new PRs in the repositories you pick, with no stacking required. But $40 a seat is a lot to pay for the reviewer alone. You get your money’s worth when the team branches through the Graphite CLI and merges through its queue, and unwinding that means changing how everyone works. Its setup docs also only describe GitHub.&lt;/p&gt;

&lt;p&gt;Graphite’s ownership has changed too. On December 19, 2025, Graphite &lt;a href="https://graphite.com/blog/graphite-joins-cursor" rel="noopener noreferrer"&gt;signed a definitive agreement to join Cursor&lt;/a&gt; (the company is Anysphere). Both companies said Graphite would keep operating as an independent product, and Graphite’s post lists plans to combine its AI reviewer with Cursor’s Bugbot into one reviewer. Since then Graphite has shipped &lt;a href="https://graphite.com/blog/cursor-cloud-agents" rel="noopener noreferrer"&gt;Cursor Cloud Agents inside Graphite&lt;/a&gt; (March 2026, for paid Cursor plans), and Cursor itself &lt;a href="https://cursor.com/blog/joining-spacex" rel="noopener noreferrer"&gt;was acquired by SpaceX&lt;/a&gt; in August 2026. Graphite works the same today, but its reviewer may change shape, and its roadmap now follows Cursor’s.&lt;/p&gt;

&lt;p&gt;If stacking is the draw, GitHub now ships native stacked pull requests in public preview, which we cover in &lt;a href="https://pyor.review/blog/github-stacked-pull-requests" rel="noopener noreferrer"&gt;GitHub stacked pull requests&lt;/a&gt;. Graphite is far more mature today, but it is no longer the only way to stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should pick which
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pick CodeRabbit&lt;/strong&gt; if you want an AI first pass on every PR without changing your workflow, you are on more than one git host, or you want the reviewer that catches the most on the open benchmark and can live with more comments to triage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick Graphite&lt;/strong&gt; if your team will actually adopt stacked PRs and a merge queue. Stacking gets you smaller PRs, and the reviewer rides along as a quiet extra that rarely wastes your time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use both&lt;/strong&gt; if you want Graphite’s stacking and CodeRabbit’s catch rate. Turn Graphite’s reviewer off on those repos, or you will read two bots on every PR.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are looking for a Graphite competitor because you only ever used the reviewer, you have the clearest case for switching: a dedicated bot does that job for less. Our &lt;a href="https://pyor.review/blog/graphite-alternatives" rel="noopener noreferrer"&gt;Graphite alternatives&lt;/a&gt; and &lt;a href="https://pyor.review/blog/coderabbit-alternatives" rel="noopener noreferrer"&gt;CodeRabbit alternatives&lt;/a&gt; posts map the rest of the field.&lt;/p&gt;

&lt;h2&gt;
  
  
  When neither is the bottleneck
&lt;/h2&gt;

&lt;p&gt;On a lot of teams (ours included), the slow part of review is a human reading a big diff. The bottleneck shifted from producing code to reviewing it. A bot adds comments to read and stacking changes how PRs are cut, but if your PRs are a 20K-line migration that cannot be stacked, or agent-written changes that land faster than anyone reads them, a reviewer bot hands you one more layer of text, and you still have to read the code anyways.&lt;/p&gt;

&lt;p&gt;That is the problem we built &lt;a href="https://pyor.review/" rel="noopener noreferrer"&gt;Pyor&lt;/a&gt; for (yes, this is the plug, kept short). Pyor is a review surface for GitHub PRs, on the web and as a desktop app for macOS, Windows, and Linux. It is not an AI reviewer, and its AI posts no comments: it groups and labels the diff and drops short hints so you read the code that matters first and skim the noise. It adds PRs to GitHub’s merge queue rather than running its own, and while it does not create stacks, it surfaces GitHub native stacks while you review. Pyor is free for individuals and $7.99 per seat a month for orgs, and it works next to either tool here. The feature-by-feature versions are in &lt;a href="https://pyor.review/blog/pyor-vs-graphite" rel="noopener noreferrer"&gt;Pyor vs Graphite&lt;/a&gt; and &lt;a href="https://pyor.review/blog/pyor-vs-coderabbit" rel="noopener noreferrer"&gt;Pyor vs CodeRabbit&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is Graphite or CodeRabbit better for AI code review?
&lt;/h3&gt;

&lt;p&gt;If the AI reviewer is all you want, CodeRabbit. On Martian’s open Code Review Bench it catches far more of the issues developers actually fix, while Graphite’s reviewer is quieter and more precise but misses most of them. What you pay Graphite for is stacked pull requests and a merge queue, and the reviewer comes with them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is CodeRabbit a Graphite competitor?
&lt;/h3&gt;

&lt;p&gt;Only on the AI review part. CodeRabbit is a dedicated review bot that plugs into GitHub, GitLab, Azure DevOps, or Bitbucket. Graphite is a workflow platform for GitHub built around stacked pull requests, a merge queue, and an inbox, with an AI reviewer as one feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can you use Graphite and CodeRabbit together?
&lt;/h3&gt;

&lt;p&gt;Yes. Graphite’s AI reviews are switched on per repository or per organization, and CodeRabbit installs as its own app, so a team can stack and merge with Graphite and let CodeRabbit post the review comments. You pay for both, and you read both if both are on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Who owns Graphite now?
&lt;/h3&gt;

&lt;p&gt;Graphite signed a definitive agreement in December 2025 to be acquired by Cursor (the company is Anysphere), and both said Graphite would keep running as an independent product. Cursor itself was acquired by SpaceX in August 2026. Graphite is still sold and priced on its own.&lt;/p&gt;

</description>
      <category>github</category>
      <category>codereview</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Interdiff Meaning: What an Interdiff Is in Code Review</title>
      <dc:creator>Othman Shareef</dc:creator>
      <pubDate>Sun, 18 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/pyor/interdiff-meaning-what-an-interdiff-is-in-code-review-22pm</link>
      <guid>https://dev.to/pyor/interdiff-meaning-what-an-interdiff-is-in-code-review-22pm</guid>
      <description>&lt;p&gt;An interdiff is the diff between two versions of the same change. Instead of re-reading a whole pull request after an update, you read only what the author changed between revision one and revision two.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The short answer:&lt;/strong&gt; The interdiff meaning is easiest to see as a diff of diffs: version one of a patch said how the code should change, version two says it differently, and the interdiff shows exactly where the two disagree. It answers the only question a returning reviewer has: what is different since I last looked?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why does re-review need an interdiff?
&lt;/h2&gt;

&lt;p&gt;First review is well supported everywhere: you get a diff against the base branch and you read it. The second review is where tooling has historically gone quiet. The author pushed fixes, maybe rebased, maybe reworked a section you never commented on, and the platform shows you either the same full diff again or a per-commit view polluted by rebase noise. So reviewers face a bad menu: re-read everything (nobody does), read nothing and approve (everybody eventually does), or reconstruct the delta by hand. An interdiff replaces that menu with the right default: show me revision two minus revision one. We walk through the workflow consequences in &lt;a href="https://pyor.review/blog/re-reviewing-pull-requests-interdiff" rel="noopener noreferrer"&gt;our piece on re-reviewing pull requests with interdiffs&lt;/a&gt;; this article is just the definition underneath it. The cost of getting this wrong is quiet: the revision that introduces a bug is precisely the one nobody re-read, because it arrived after the hard first pass was already done. Reviewers approve version one carefully and version four on trust, and the delta between those two readings is where regressions live.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interdiff meaning in git: the range-diff command
&lt;/h2&gt;

&lt;p&gt;Git ships the idea natively as &lt;a href="https://git-scm.com/docs/git-range-diff" rel="noopener noreferrer"&gt;git range-diff&lt;/a&gt;, which compares two commit ranges, typically two versions of the same branch, and shows which commits correspond, which were added or dropped, and how each corresponding commit changed. After a force-push you can run something like &lt;code&gt;git range-diff main old-tip new-tip&lt;/code&gt; and read precisely what the rework did, rebase and all. The name interdiff itself is older: a standalone utility of that name compared two patch files back when changes traveled as emailed patches, and kernel reviewers still routinely ask contributors to post a range-diff alongside v2 of a patch series.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where do patchsets come from? The Gerrit heritage
&lt;/h2&gt;

&lt;p&gt;Gerrit, the review system built around the Android project, made revisions first-class: every push to a change under review becomes a numbered patchset, and the UI lets a reviewer diff any patchset against any other. Comment positions carry across revisions, so a thread you opened on patchset 2 is still anchored correctly when you are comparing patchset 2 to patchset 5. That lineage is why review veterans talk about patchsets and interdiffs in the same breath: Gerrit demonstrated that re-review is a solved problem when versions of a change are modeled explicitly rather than as an afterthought.&lt;/p&gt;

&lt;h2&gt;
  
  
  What GitHub gives you, and where it falls short
&lt;/h2&gt;

&lt;p&gt;GitHub approximates the interdiff. It can show changes since your last review, and &lt;a href="https://pyor.review/blog/github-viewed-files" rel="noopener noreferrer"&gt;viewed-file checkmarks&lt;/a&gt; reset when a file changes, which together cover the easy case: new commits appended to the same history. The approximation degrades exactly where you need it most. A rebase or force-push rewrites the commits the comparison was anchored to, comments go outdated, and the since-review view can fall back to showing you everything again. There is no patchset picker, no durable revision history to diff against. Until the platform models revisions properly, reviewers cover the gap with &lt;code&gt;git range-diff&lt;/code&gt; locally or with review tools built around the returning reviewer (disclosure: our own &lt;a href="https://pyor.review/" rel="noopener noreferrer"&gt;Pyor&lt;/a&gt; is one attempt at that). However you get one, the test of a review tool is the second look, not the first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fntk8ujxjnj4m0wnflbzs.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fntk8ujxjnj4m0wnflbzs.webp" alt="A commit rail on the left with four commits, the second one selected with its message, and the diff scoped to only that commit: twelve files instead of the pull request's nineteen." width="800" height="524"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A commit rail as the revision picker: select a commit and the diff re-scopes to that span.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is the difference between an interdiff and git range-diff?
&lt;/h3&gt;

&lt;p&gt;An interdiff is the concept: the difference between two versions of a change. git range-diff is the built-in git command that produces one, comparing two commit ranges and showing how each commit changed between them. Older tooling also had a literal interdiff utility for comparing patch files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does GitHub show an interdiff?
&lt;/h3&gt;

&lt;p&gt;Approximately. GitHub can show changes since your last review, and its viewed-files checkmarks reset when a file changes. But a force-push rewrites history and can break that view, and there is no first-class revision picker like Gerrit patchsets, so the approximation fails exactly when rebases happen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why not just re-read the whole pull request?
&lt;/h3&gt;

&lt;p&gt;Because full re-reads do not scale and reviewers do not actually do them. Faced with a 40-file PR updated for the third time, most reviewers skim and approve. An interdiff shrinks the third look to the handful of lines that changed, which keeps re-review honest.&lt;/p&gt;

</description>
      <category>github</category>
      <category>codereview</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>What Are Stacked Pull Requests?</title>
      <dc:creator>Othman Shareef</dc:creator>
      <pubDate>Fri, 16 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/pyor/what-are-stacked-pull-requests-13oi</link>
      <guid>https://dev.to/pyor/what-are-stacked-pull-requests-13oi</guid>
      <description>&lt;p&gt;Stacked pull requests are a chain of dependent PRs where each one builds on the branch of the previous. A large change is split into small steps, reviewed independently, and merged from the bottom of the stack up.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The short answer:&lt;/strong&gt; What are stacked pull requests solving? The conflict between how developers work and how reviewers read. Big features are built in sequence, but nobody reviews a 2,000-line diff well. A stack keeps the author moving on step three while steps one and two are under review, and every reviewer only ever sees a small, coherent piece.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How do stacked pull requests work?
&lt;/h2&gt;

&lt;p&gt;Instead of one feature branch targeting main, you cut a chain: branch A off main, branch B off A, branch C off B. Each branch becomes a pull request whose base is the branch below it, so every diff shows only that step. Say you are adding an export feature: PR one adds the data model, PR two the API endpoint on top of it, PR three the UI on top of that. Review and merge run bottom up. PR one merges into main first; PR two is then retargeted onto main and merged; PR three follows. When a lower PR changes in response to review, the branches above it are rebased so the stack stays consistent. That rebase cascade is the tax the whole workflow lives with, and we will come back to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are stacked pull requests for?
&lt;/h2&gt;

&lt;p&gt;Small diffs get better reviews; that is one of the most consistent findings in review practice, and it is the core argument in our guide to &lt;a href="https://pyor.review/blog/how-big-should-a-pull-request-be" rel="noopener noreferrer"&gt;how big a pull request should be&lt;/a&gt;. The problem is that real features are often irreducibly large. Without a stack, the author faces a bad choice: ship one huge PR that gets skimmed, or sit blocked waiting for each small PR to merge before starting the next. Stacking removes the wait. The author keeps building on their own unmerged work while review proceeds underneath, and each reviewer gets a diff sized for actual reading. It is the same instinct behind &lt;a href="https://pyor.review/blog/atomic-commits-reviewable-prs" rel="noopener noreferrer"&gt;atomic commits&lt;/a&gt;, promoted from commit granularity to PR granularity.&lt;/p&gt;

&lt;h2&gt;
  
  
  What tools support stacking?
&lt;/h2&gt;

&lt;p&gt;GitHub has begun building stacks in natively: as &lt;a href="https://www.infoworld.com/article/4158575/github-adds-stacked-prs-to-speed-complex-code-reviews.html" rel="noopener noreferrer"&gt;InfoWorld reported&lt;/a&gt;, GitHub added stacked pull requests specifically to speed up review of complex changes. Since 30 July 2026 it has been in public preview for every repository, no waitlist, though still labelled subject to change; we track the details in our deeper look at &lt;a href="https://pyor.review/blog/github-stacked-pull-requests" rel="noopener noreferrer"&gt;GitHub stacked pull requests&lt;/a&gt;. In the meantime the workflow is well served by third-party tools (Graphite is the best known) that automate the branch bookkeeping: creating the chain, restacking after changes, and retargeting PRs as lower ones merge. And plain GitHub works too, manually, for shallow stacks. The broader tool landscape is covered in our roundup of &lt;a href="https://pyor.review/blog/github-pr-review-alternatives" rel="noopener noreferrer"&gt;GitHub PR review alternatives&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do stacks cost?
&lt;/h2&gt;

&lt;p&gt;The honest ledger has three entries. First, rebase overhead: every change to a lower PR ripples upward, and without tooling you pay that in manual rebases and force-pushes. Second, review coordination: reviewers of PR three are looking at code built on unreviewed foundations, and feedback on PR one can invalidate work above it. Third, platform friction: force-pushing rebased branches can confuse review state, resetting what reviewers had already read. None of this is disqualifying, but it means stacks are a deliberate practice, not a free upgrade. Use them when the work is genuinely large and sequential, keep each layer independently understandable, and let the bottom of the stack merge fast. A stack whose base PR sits unreviewed for a week is just a big PR with extra steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can you create stacked pull requests on GitHub without extra tools?
&lt;/h3&gt;

&lt;p&gt;Yes. Open each branch against the one below it instead of against main, then merge from the bottom and retarget as you go. It works, but keeping the stack rebased by hand gets tedious past two or three PRs, which is why dedicated stacking tools exist.&lt;/p&gt;

&lt;h3&gt;
  
  
  How is a stacked pull request different from a normal branch with many commits?
&lt;/h3&gt;

&lt;p&gt;A multi-commit branch still lands as one pull request with one review and one merge. A stack splits the same work into separate PRs, each with its own reviewer, discussion, CI run, and merge, so review happens in small units while the work stays connected.&lt;/p&gt;

&lt;h3&gt;
  
  
  When are stacked pull requests not worth it?
&lt;/h3&gt;

&lt;p&gt;When the change is already small, or when the pieces are truly independent and could just be separate unrelated PRs. Stacks pay off when work is large and sequential. If your team rarely reviews within a day, the coordination cost of a stack can exceed its benefit.&lt;/p&gt;

</description>
      <category>github</category>
      <category>codereview</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Nit Code Review Meaning: What a Nit Comment Is</title>
      <dc:creator>Othman Shareef</dc:creator>
      <pubDate>Wed, 14 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/pyor/nit-code-review-meaning-what-a-nit-comment-is-13nh</link>
      <guid>https://dev.to/pyor/nit-code-review-meaning-what-a-nit-comment-is-13nh</guid>
      <description>&lt;p&gt;In code review, a nit is a minor, non-blocking comment: a small point about style, naming, or polish that the reviewer wants to mention but does not consider a reason to hold up approval. The word is short for nitpick.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The short answer:&lt;/strong&gt; The nit code review meaning, compressed: prefixing a comment with &lt;code&gt;nit:&lt;/code&gt; tells the author this is worth a glance, not a fight. It keeps small feedback flowing without turning every review into a negotiation, and it only works if both sides honor the label: reviewers keep nits genuinely optional, authors read them anyway.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Nit code review meaning: what does the prefix signal?
&lt;/h2&gt;

&lt;p&gt;A review comment carries two messages: the observation itself, and how much the reviewer cares. The &lt;code&gt;nit:&lt;/code&gt; prefix makes the second part explicit. It says: I noticed this, I would do it differently, and I am approving either way. That framing is the whole value. Without it, the author has to guess whether a comment about a variable name is a passing thought or a condition for approval, and guessing wrong in either direction wastes a round trip. The &lt;a href="https://conventionalcomments.org/" rel="noopener noreferrer"&gt;Conventional Comments&lt;/a&gt; spec generalizes this idea into a full vocabulary: labels like &lt;code&gt;suggestion&lt;/code&gt;, &lt;code&gt;question&lt;/code&gt;, &lt;code&gt;issue&lt;/code&gt;, and &lt;code&gt;nitpick&lt;/code&gt;, plus decorations like &lt;code&gt;(non-blocking)&lt;/code&gt; that make severity unambiguous. You do not need the whole system to benefit; even adopting &lt;code&gt;nit:&lt;/code&gt; alone removes a surprising amount of friction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nit etiquette for reviewers
&lt;/h2&gt;

&lt;p&gt;A nit is a courtesy, and it stays one only under a few rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mean the label.&lt;/strong&gt; If you would withhold approval over it, it is not a nit. Do not write &lt;code&gt;nit:&lt;/code&gt; and then argue three replies deep.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Say the fix, not just the flaw.&lt;/strong&gt; A nit that names the preferred spelling costs the author seconds; a vague one costs a guess. Our guide to &lt;a href="https://pyor.review/blog/review-comments-that-land" rel="noopener noreferrer"&gt;review comments that land&lt;/a&gt; applies doubly to small ones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ration them.&lt;/strong&gt; Ten nits on a solid change read as hostility, however polite each one is. We covered the failure mode at length in &lt;a href="https://pyor.review/blog/code-review-nitpicks" rel="noopener noreferrer"&gt;our piece on code review nitpicks&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automate the recurring ones.&lt;/strong&gt; A nit you have typed three times is a linter rule waiting to be written. Machines nitpick for free and nobody resents them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Nit etiquette for authors
&lt;/h2&gt;

&lt;p&gt;Non-blocking does not mean ignorable. The gracious move is to fix cheap nits in the next push, reply briefly to the ones you are declining, and resolve the threads either way so the reviewer is not left wondering. Silently skipping every nit trains reviewers to escalate small feedback into blocking feedback, which makes reviews slower for everyone. Treat nits as free polish from someone who read your code closely, because that is what they are.&lt;/p&gt;

&lt;p&gt;There is a mechanical courtesy here too: on GitHub, who resolves the thread matters. For a nit you fixed, resolving it yourself with a quick done is fine. For one you are declining, leave the thread open long enough for the reviewer to see your reasoning before it disappears. We cover the finer points in our guide to &lt;a href="https://pyor.review/blog/resolve-conversation-etiquette" rel="noopener noreferrer"&gt;resolve conversation etiquette&lt;/a&gt;, but the principle is short: a nit deserves an acknowledgment, not a burial.&lt;/p&gt;

&lt;h2&gt;
  
  
  When is a nit not a nit?
&lt;/h2&gt;

&lt;p&gt;The label gets misused in both directions. Reviewers sometimes soften real problems with it: a swallowed exception or an off-by-one is not a nit, and prefixing it as one buries a defect under politeness. The reverse misuse is the blocking nit, where a style preference arrives labeled as small but is defended like a design principle. A quick test for both: would this comment survive being ignored? If ignoring it risks a bug, drop the prefix and say so plainly. If ignoring it costs nothing but your aesthetic satisfaction, keep the prefix and let it go. The nit convention works precisely because the label is honest; spend it carelessly and your reviews lose their signal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Do I have to fix nit comments before merging?
&lt;/h3&gt;

&lt;p&gt;Usually no. A nit is non-blocking by definition, so the author can fix it, defer it, or decline it with a short reply. Teams differ on convention, though: some expect nits to be addressed in the same pull request, so check what your reviewers actually expect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where does the term nit come from?
&lt;/h3&gt;

&lt;p&gt;It is short for nitpick, picking small insects from hair, which became slang for fussing over trivial details. Code review adopted the abbreviation as a comment prefix so reviewers could flag minor polish issues while making clear the feedback is small and not a blocker.&lt;/p&gt;

&lt;h3&gt;
  
  
  How many nits are too many?
&lt;/h3&gt;

&lt;p&gt;When nits outnumber substantive comments, the review starts to read as criticism of the author rather than the code, and the important feedback drowns. A common ceiling is a handful per review; past that, ask whether a linter or formatter should be enforcing the pattern instead.&lt;/p&gt;

</description>
      <category>github</category>
      <category>codereview</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>What Does LGTM Mean in Code Review?</title>
      <dc:creator>Othman Shareef</dc:creator>
      <pubDate>Mon, 12 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/pyor/what-does-lgtm-mean-in-code-review-550o</link>
      <guid>https://dev.to/pyor/what-does-lgtm-mean-in-code-review-550o</guid>
      <description>&lt;p&gt;LGTM means looks good to me. In code review it is shorthand for approval: the reviewer has read the change, found nothing blocking, and is happy for it to merge.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The short answer:&lt;/strong&gt; So what does LGTM mean when you actually type it? It is a claim, not a pleasantry: I read this change carefully enough to vouch for it. On a two-line fix that claim is cheap to make honestly. On a forty-file change it is either the product of real work or it is rubber-stamping wearing a friendly acronym.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Where does LGTM come from?
&lt;/h2&gt;

&lt;p&gt;The acronym predates modern tooling; it grew up on open source mailing lists and early review threads as a compact way to say the patch passes. What made it a term of art is that big engineering cultures formalized it. At Google, the internal review tool Critique makes LGTM a literal, named approval state that reviewers grant, as described in &lt;a href="https://research.google/pubs/modern-code-review-a-case-study-at-google/" rel="noopener noreferrer"&gt;Modern Code Review: A Case Study at Google&lt;/a&gt;. From there the word leaked into the general vocabulary: GitHub reviewers write it in approval comments, bots print it, and stickers exist. The mechanics differ by platform, but the meaning has stayed stable for decades: a named human is signing off.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does LGTM mean in practice?
&lt;/h2&gt;

&lt;p&gt;An approval asserts more than most people think. When you approve, you are telling your team three things: the change does what its description claims, you looked hard enough to catch the problems you are qualified to catch, and you are comfortable with this code running in production with your name in the review log. That is why the flip side matters too: knowing &lt;a href="https://pyor.review/blog/when-to-request-changes" rel="noopener noreferrer"&gt;when to request changes instead&lt;/a&gt; is what keeps the approval meaningful. A reviewer who never blocks anything is not agreeable; they are absent. LGTM only carries information if it was possible for you to say something else.&lt;/p&gt;

&lt;h2&gt;
  
  
  When is a bare LGTM fine, and when is it rubber-stamping?
&lt;/h2&gt;

&lt;p&gt;A bare LGTM is perfectly good feedback when the change is small, the behavior is easy to verify, and the author is trusted on this part of the codebase. A dependency bump with green CI, a typo fix, a config value change you double-checked: adding paragraphs of commentary there is ceremony for its own sake. The trouble starts when LGTM becomes the default response to everything, including changes nobody could have read in the time between request and approval. We wrote a whole piece on &lt;a href="https://pyor.review/blog/lgtm-culture-code-review-theatre" rel="noopener noreferrer"&gt;LGTM culture and code review theater&lt;/a&gt;: the short version is that the acronym is not the problem, the missing reading is. A useful self-test: if you cannot name one specific thing you checked, you did not review it, you witnessed it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related shorthand: PTAL, nit, WIP
&lt;/h2&gt;

&lt;p&gt;LGTM lives in a small family of review abbreviations worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PTAL&lt;/strong&gt; : please take a look. A request for review, or for re-review after fixes have been pushed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;nit&lt;/strong&gt; : short for nitpick. Prefixes a minor, non-blocking comment; we cover the etiquette in &lt;a href="https://pyor.review/blog/code-review-nitpicks" rel="noopener noreferrer"&gt;our piece on review nitpicks&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WIP&lt;/strong&gt; : work in progress. Marks a pull request that is not ready for formal review; on GitHub this is now usually a draft PR instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ACK / NACK&lt;/strong&gt; : acknowledge or reject, an older sibling of LGTM from mailing list review culture.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of this shorthand exists to keep review fast without making it empty. LGTM is the smallest possible review comment, and that is exactly why it deserves the discipline: it should compress a real judgment, not replace one. If your team wants the compression without the emptiness, make the convention explicit: a bare LGTM is reserved for trivial changes, everything else gets one line about what was checked, and an LGTM you feel pressured into giving is really a signal to slow down. Shorthand works best when everyone knows exactly how much weight it carries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is LGTM the same as approving a pull request?
&lt;/h3&gt;

&lt;p&gt;Not automatically. LGTM is just text; on GitHub, approval is a formal review state that satisfies branch protection rules. Many reviewers write LGTM in the comment of an approving review, so in practice the two travel together, but only the Approve action unblocks the merge.&lt;/p&gt;

&lt;h3&gt;
  
  
  What does PTAL mean?
&lt;/h3&gt;

&lt;p&gt;PTAL stands for please take a look. Authors use it to ask a reviewer to look at a change, or to look again after they have pushed fixes. It is the request side of the exchange that LGTM closes: PTAL asks for review, LGTM signals the reviewer is satisfied.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is it rude to reply with just LGTM?
&lt;/h3&gt;

&lt;p&gt;Not rude, but it can be low-signal. On a small, easily verified change, a bare LGTM is fine. On anything substantial, one sentence about what you checked makes the approval mean something and tells the author which parts were actually read rather than skimmed.&lt;/p&gt;

</description>
      <category>github</category>
      <category>codereview</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>What Is a Pull Request Review? A Plain Definition</title>
      <dc:creator>Othman Shareef</dc:creator>
      <pubDate>Sat, 10 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/pyor/what-is-a-pull-request-review-a-plain-definition-5h8c</link>
      <guid>https://dev.to/pyor/what-is-a-pull-request-review-a-plain-definition-5h8c</guid>
      <description>&lt;p&gt;A pull request review is a structured check of proposed code changes before they merge. A teammate reads the diff, leaves comments, and either approves the change or requests changes, so problems are caught while they are still cheap to fix.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The short answer:&lt;/strong&gt; What is a pull request review, in one breath? It is the checkpoint between written code and shipped code: a second person confirms the change does what it claims, fits the codebase, and will not surprise whoever maintains it next. The approval is an assertion, not a formality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How does a pull request review work on GitHub?
&lt;/h2&gt;

&lt;p&gt;The author opens a pull request, a proposal to merge one branch into another, and requests reviewers, either by hand or automatically through code owner rules. The reviewer opens the Files changed tab, reads the diff, and attaches comments to specific lines. Comments can carry questions, requested fixes, or concrete suggestions the author can apply with one click. When the reviewer is done reading, they submit the review with one of three verdicts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Comment&lt;/strong&gt; : feedback without a judgment, useful when you have notes but no authority or no strong opinion on merging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approve&lt;/strong&gt; : the change is good to merge as far as this reviewer is concerned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request changes&lt;/strong&gt; : the change should not merge until specific problems are addressed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The author replies, pushes fixes, and asks for another look; each comment becomes a thread that gets resolved as the discussion settles. Branch protection rules can make all of this binding by requiring one or more approvals before the merge button works, which turns review from a courtesy into a gate.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a pull request review actually for?
&lt;/h2&gt;

&lt;p&gt;Ask most developers and they will say finding bugs. That is part of it, but the research says it is not the biggest part. A well-known Microsoft study of code review in practice, &lt;a href="https://www.microsoft.com/en-us/research/publication/expectations-outcomes-and-challenges-of-modern-code-review/" rel="noopener noreferrer"&gt;Expectations, Outcomes, and Challenges of Modern Code Review&lt;/a&gt;, found that while defect finding is the top stated motivation, the actual outcomes lean toward code improvement, alternative solutions, and knowledge transfer. Review is how a team keeps a shared mental model of its own codebase: the reviewer learns what changed, the author learns what the team expects, and the code ends up readable by more than one person. We have written before about &lt;a href="https://pyor.review/blog/do-code-reviews-find-bugs" rel="noopener noreferrer"&gt;what reviews actually catch&lt;/a&gt;, and the honest answer is: fewer bugs than you hope, more understanding than you expect. Both are worth paying for.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does a good pull request review look like?
&lt;/h2&gt;

&lt;p&gt;A good review starts before the line-by-line reading: understand what the change is supposed to do, then check whether it does that, then look at how. Concretely, strong reviewers tend to do a few consistent things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read the description and linked issue first, so the diff has context.&lt;/li&gt;
&lt;li&gt;Start with the riskiest files, not the first ones alphabetically.&lt;/li&gt;
&lt;li&gt;Comment with reasons, not just verdicts, and separate blocking from optional.&lt;/li&gt;
&lt;li&gt;Approve explicitly when satisfied instead of going silent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want the full checklist treatment, we keep a &lt;a href="https://pyor.review/blog/code-review-checklist" rel="noopener noreferrer"&gt;practical code review checklist&lt;/a&gt; that covers correctness, tests, security, and readability in order. And when the diff is overwhelming, the problem is usually the pull request, not you; there are concrete tactics for &lt;a href="https://pyor.review/blog/how-to-review-large-pull-requests" rel="noopener noreferrer"&gt;reviewing large pull requests&lt;/a&gt; without skimming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where do pull request reviews go wrong?
&lt;/h2&gt;

&lt;p&gt;Two failure modes cover most of it. The first is the rubber stamp: an approval given without real reading, which keeps the ritual while deleting the value. The second is the bottleneck: reviews that sit for days, punishing exactly the authors who split their work into small, reviewable pieces. Both have the same root cause, review treated as interruption rather than as first-class engineering work. Teams that treat it as the latter, with time carved out and expectations set, get the defect prevention and the shared understanding. Teams that do not get theater. The definition is simple; the discipline is the hard part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is the difference between a code review and a pull request review?
&lt;/h3&gt;

&lt;p&gt;Code review is the general practice of having another person examine code changes. A pull request review is the specific form most teams use today: the review happens on a pull request, inside a platform like GitHub, with comments anchored to the diff and an explicit approve or request changes verdict.&lt;/p&gt;

&lt;h3&gt;
  
  
  Who can review a pull request?
&lt;/h3&gt;

&lt;p&gt;Anyone with read access to the repository can comment on a pull request. Approving or requesting changes usually requires write access, and branch protection rules can require approval from specific people, such as code owners, before the change is allowed to merge.&lt;/p&gt;

&lt;h3&gt;
  
  
  How long should a pull request review take?
&lt;/h3&gt;

&lt;p&gt;Minutes to a few hours of focused reading for a well-sized change; the elapsed time matters more. Many teams target a first response within one business day, because waiting reviews block the author. If a review takes days of reading, the pull request itself is probably too large.&lt;/p&gt;

</description>
      <category>github</category>
      <category>codereview</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>GitHub Auto Merge: Good Uses and the Stale Approval Trap</title>
      <dc:creator>Othman Shareef</dc:creator>
      <pubDate>Thu, 08 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/pyor/github-auto-merge-good-uses-and-the-stale-approval-trap-3b6d</link>
      <guid>https://dev.to/pyor/github-auto-merge-good-uses-and-the-stale-approval-trap-3b6d</guid>
      <description>&lt;p&gt;GitHub auto merge is one of those features that is either a pure quality-of-life win or a quiet hole in your review process, depending entirely on settings most teams have never audited. The behavior itself is simple and documented in &lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/automatically-merging-a-pull-request" rel="noopener noreferrer"&gt;GitHub’s auto-merge docs&lt;/a&gt;: enable it on a PR, and the PR merges itself the moment all requirements are met. The interesting questions are when that is a good idea, and what “requirements are met” can silently fail to mean.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The short answer:&lt;/strong&gt; Auto-merge is excellent for exactly one situation: the human review is done and only machinery remains. Approved and waiting on CI, or a dependency bump you have actually read. The trap is stale approvals: if branch protection does not dismiss approvals when new commits are pushed, auto-merge will happily merge code added after the reviewer looked. Audit that setting before you trust the feature with anything.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How GitHub auto merge actually works
&lt;/h2&gt;

&lt;p&gt;The verified mechanics: auto-merge must be allowed at the repository level, and then people with write permissions can enable it on individual pull requests. Per the docs, the option is relevant for PRs that cannot merge yet because requirements are unmet, and once enabled “the pull request will merge automatically when all required reviews are met and all required status checks have passed.” You choose the merge method and can set the commit message when enabling. One safety behavior worth knowing: if someone without write permissions pushes new changes to the head branch, or switches the base branch, auto-merge is disabled automatically, so a drive-by commit from an outside contributor cannot ride an armed auto-merge into your default branch. Note the asymmetry, because it matters later: pushes from people &lt;em&gt;with&lt;/em&gt; write access do not disarm it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The good uses
&lt;/h2&gt;

&lt;p&gt;The canonical case is approved-pending-CI. Review is finished, the reviewer signed off, and the only thing between the branch and main is a forty-minute pipeline. Without auto-merge, someone has to remember to come back, which in practice means the PR merges hours later or the next morning, and every hour it sits is another chance for a conflict to appear. Enabling auto-merge at approval time converts “merged whenever someone remembers” into “merged on green.” The second good case is routine dependency updates, with a hard caveat: after a real review. A Renovate bump whose changelog and diff you have &lt;a href="https://pyor.review/blog/reviewing-dependency-updates" rel="noopener noreferrer"&gt;actually examined&lt;/a&gt; is a fine thing to auto-merge behind CI. Auto-merging dependency PRs you never opened is a different practice, and it is not review. The tell is simple: if you could not say what changed in the dependency, the merge was unattended, whoever technically clicked approve.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trap: stale approvals plus new commits
&lt;/h2&gt;

&lt;p&gt;Here is the failure sequence, and every step is individually reasonable. A reviewer approves. The author enables auto-merge. CI fails on a flake or a lint error, so the author pushes another commit, or force-pushes a rebase with a quick fix folded in. The author has write access, so auto-merge stays armed. And if your branch protection does not dismiss stale approvals when new commits are pushed, the original approval still counts. The instant checks go green, the PR merges, including commits no reviewer ever saw. Nothing malicious happened; the process just never asked anyone to look again. Whether it can happen to you is one checkbox: the dismiss-stale-approvals setting in your required-review rules, which we cover in &lt;a href="https://pyor.review/blog/github-branch-protection-required-reviews" rel="noopener noreferrer"&gt;branch protection and required reviews&lt;/a&gt;. If auto-merge is enabled anywhere, that setting stops being optional hygiene and becomes the thing standing between “approved code merges” and “approved-ish code merges.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Auto-merge reviews nothing
&lt;/h2&gt;

&lt;p&gt;A subtler cost shows up in culture. Once merging is automatic, approval becomes the last human act in the pipeline, and anything that erodes approval quality now flows straight to main with no further pause for doubt. Auto-merge fires on requirements-satisfied; it cannot distinguish a careful approval from a &lt;a href="https://pyor.review/blog/lgtm-culture-code-review-theatre" rel="noopener noreferrer"&gt;reflexive LGTM&lt;/a&gt;. Teams sometimes experience this as “auto-merge lowered our quality,” but the feature only removed the slack that was hiding rubber stamps. If merges feel scarier when automated, the review step was weaker than assumed, and that diagnosis is worth its own conversation. The same logic cuts the other way, constructively: a team whose approvals are consistently trustworthy loses nothing to auto-merge and gains hours of unblocked time per week. The feature is a mirror, not a gate. It shows you what your approvals were already worth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The checklist before you trust it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dismiss stale approvals&lt;/strong&gt; is on for protected branches, or you have a conscious, written reason it is not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Required checks actually cover the risk.&lt;/strong&gt; Auto-merge waits only on checks you marked required; an optional-but-important suite will not hold the merge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approvals mean review happened.&lt;/strong&gt; Automation amplifies whatever your approval habit is, stamp or scrutiny.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-throughput repos consider a merge queue&lt;/strong&gt; on top, which serializes landings; we cover it in &lt;a href="https://pyor.review/blog/github-merge-queue-explained" rel="noopener noreferrer"&gt;our merge queue explainer&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pass that audit and auto-merge is what it should be: the removal of a pointless wait, after the reviewing is truly done. Fail it, and the feature will do exactly what you configured, which is not the same as what you intended.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How does auto-merge work on a GitHub pull request?
&lt;/h3&gt;

&lt;p&gt;Someone with write permission enables auto-merge on an individual PR, after the feature is turned on at the repository level. The PR then merges automatically once all required reviews are met and all required status checks have passed. You pick the merge method up front, and GitHub disables auto-merge if someone without write access pushes to the branch or the base branch changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is it safe to enable auto-merge before CI finishes?
&lt;/h3&gt;

&lt;p&gt;That is its best use, with one condition: the human review must already be genuinely complete. If the code is approved and only checks remain, auto-merge just removes the ritual of returning to click a button. The risk appears when new commits can land after approval; unless branch protection dismisses stale approvals, those commits can merge unreviewed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does auto-merge skip code review?
&lt;/h3&gt;

&lt;p&gt;No. Auto-merge respects your branch protection rules, so required reviews still gate the merge. But it also cannot add scrutiny: it fires the moment requirements read as satisfied, whether the approval was thoughtful or a rubber stamp, fresh or stale. Auto-merge automates the clicking, and it inherits exactly the review rigor your settings and culture enforce.&lt;/p&gt;

</description>
      <category>github</category>
      <category>codereview</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>GitHub Resolve Conversation: Who Should Close the Thread</title>
      <dc:creator>Othman Shareef</dc:creator>
      <pubDate>Tue, 06 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/pyor/github-resolve-conversation-who-should-close-the-thread-22f8</link>
      <guid>https://dev.to/pyor/github-resolve-conversation-who-should-close-the-thread-22f8</guid>
      <description>&lt;p&gt;Every team that reviews code on GitHub eventually has the argument, usually in a PR thread that was already tense. Someone hits the GitHub resolve conversation button on a comment they did not write, and the person who wrote it notices. Was the concern addressed, or dismissed? GitHub is no help here: the button collapses the thread and marks it resolved, and the platform is agnostic about who clicks it. The etiquette is entirely a team norm, which means most teams have three conflicting norms and no document.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The short answer:&lt;/strong&gt; The defensible default: the author replies to the comment and pushes the fix, and the commenter resolves the thread. Whoever raised the concern is the only person who can confirm it was actually met, so resolution should be their acknowledgment, not the author’s self-grade. The exception is feedback the reviewer pre-labeled as optional: take-it-or-leave-it nits are the author’s call, and the author may resolve them directly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The GitHub resolve conversation norm nobody writes down
&lt;/h2&gt;

&lt;p&gt;There are two coherent positions. Author-resolves says the author is the janitor of their own PR: they act on feedback, they tidy the threads, and a wall of resolved conversations signals a change that is ready. Commenter-resolves says a thread is a question addressed to its author, and only the person who asked can say the answer satisfied them. Both work when everyone shares the assumption. What breaks teams is the mixture: an author who thinks resolving is bookkeeping meets a reviewer who thinks it is an answer to their question being closed unread. The classic Microsoft research on &lt;a href="https://www.microsoft.com/en-us/research/publication/expectations-outcomes-and-challenges-of-modern-code-review/" rel="noopener noreferrer"&gt;modern code review&lt;/a&gt; found that review is as much a communication channel as a defect filter, and the resolve button is part of that channel; clicking it transmits something whether you intend to or not.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the ambiguity actually costs
&lt;/h2&gt;

&lt;p&gt;The cost lands at re-review time. A reviewer coming back after the author pushes fixes faces a stack of threads in mixed states: some resolved by the author, some open but answered, some open and forgotten. Which ones still need their attention? If resolved might mean “fixed and verified” or might mean “the author decided it was fine,” the reviewer has to reopen and reread everything to be safe, which is precisely the wasted pass we describe in &lt;a href="https://pyor.review/blog/re-reviewing-pull-requests-interdiff" rel="noopener noreferrer"&gt;re-reviewing pull requests&lt;/a&gt;. Unresolved-thread limbo has a second failure mode: PRs that merge with open threads nobody can later interpret. Six months on, an open thread that says “this will break under concurrent writes” with no reply is either a landmine or noise, and nobody can tell which. The archaeology cost is real: someone eventually spends an afternoon reconstructing whether a warning was heeded, and the thread state could have answered in one glance.&lt;/p&gt;

&lt;h2&gt;
  
  
  A defensible default
&lt;/h2&gt;

&lt;p&gt;The protocol that keeps the signal clean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The author replies to every thread&lt;/strong&gt; , even trivially: “fixed in the next push,” “disagree, here is why,” or “good catch, done.” A push with no reply forces the reviewer to diff-hunt for whether their comment was acted on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The author pushes the fix&lt;/strong&gt; and references it in the reply when the fix is not obvious.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The commenter resolves.&lt;/strong&gt; They raised the concern; their click is the confirmation it was met. Resolution becomes a tiny handshake instead of a unilateral declaration, and the resolved state acquires a precise meaning: the person who asked is satisfied. That precision is the entire point of having a norm.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stale threads default to a ping, not a resolve.&lt;/strong&gt; If the commenter goes silent for days, the author asks once, then resolves with a note. Silence should not block merges forever, but the note preserves the record.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The exceptions that prove the rule
&lt;/h2&gt;

&lt;p&gt;Commenter-resolves is the default, not a ritual. Feedback the reviewer explicitly marked as optional, the &lt;a href="https://conventionalcomments.org/" rel="noopener noreferrer"&gt;Conventional Comments&lt;/a&gt; style of &lt;strong&gt;nit:&lt;/strong&gt; or &lt;strong&gt;suggestion (non-blocking):&lt;/strong&gt;, transfers the decision to the author, and with it the resolve. Making the author round-trip every take-it-or-leave-it comment back to the reviewer is ceremony with no information content, and it is how teams learn to hate the protocol. The prerequisite is honest labeling: reviewers have to actually mark their nits as nits, a discipline we cover in &lt;a href="https://pyor.review/blog/code-review-nitpicks" rel="noopener noreferrer"&gt;our piece on nitpicks&lt;/a&gt;. The other sane exception is threads the commenter is no longer around to resolve; departed colleagues should not hold locks on your merge button.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write the norm down
&lt;/h2&gt;

&lt;p&gt;Whatever you choose, choose it in a document instead of in each PR separately. Two sentences in the contributing guide end the argument permanently: who resolves, and what the exception for pre-labeled nits is. New hires absorb it in their first PR instead of guessing, and nobody has to litigate intent inside a thread that is already about something else. This is the general lesson of &lt;a href="https://pyor.review/blog/code-review-culture" rel="noopener noreferrer"&gt;healthy review culture&lt;/a&gt;: friction comes less from strictness than from unstated rules enforced inconsistently. A team that resolves threads predictably gets a concrete payoff, because thread state becomes trustworthy. Resolved means confirmed, open means pending, and a re-reviewer can navigate by that state instead of rereading the whole conversation. It is a one-line policy that buys back real review time every single week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Who should resolve a conversation on a GitHub pull request?
&lt;/h3&gt;

&lt;p&gt;GitHub does not enforce an answer, so it is a team norm. The default we recommend: the author replies and pushes the fix, and the person who raised the comment resolves the thread, because they are the one who can confirm the concern was actually addressed. The clean exception is comments the reviewer explicitly labeled as optional nits, which the author may resolve directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is it rude to resolve someone else’s review comment?
&lt;/h3&gt;

&lt;p&gt;Rude is the wrong frame; the issue is information. When an author resolves a reviewer’s thread, they are declaring the concern handled on the reviewer’s behalf, and the reviewer may never see the reply because collapsed threads are easy to skip. On teams without an explicit norm it often reads as dismissive even when the fix is genuinely correct.&lt;/p&gt;

&lt;h3&gt;
  
  
  What happens when review threads are left unresolved?
&lt;/h3&gt;

&lt;p&gt;The PR accumulates ambiguity. A reviewer returning for a second pass cannot tell which threads represent accepted fixes, open disagreements, or things the author simply missed, so they either reread everything or approve with doubts. Unresolved threads are exactly the kind of state that makes re-review expensive, which is a cost teams routinely underprice.&lt;/p&gt;

</description>
      <category>github</category>
      <category>codereview</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>GitHub Mark File as Viewed: Keep Your Place in Big PRs</title>
      <dc:creator>Othman Shareef</dc:creator>
      <pubDate>Sun, 04 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/pyor/github-mark-file-as-viewed-keep-your-place-in-big-prs-4ff4</link>
      <guid>https://dev.to/pyor/github-mark-file-as-viewed-keep-your-place-in-big-prs-4ff4</guid>
      <description>&lt;p&gt;Buried in the corner of every file header on the Files changed tab is the most underrated control in GitHub’s review UI. The GitHub mark file as viewed checkbox does one small thing: it remembers which files you have already read. In a five-file PR that is pointless. In a fifty-file PR it is the difference between a systematic pass and rereading the same test fixture four times. This piece covers the verified behavior, the workflow that gets the most from it, and the gaps that eventually send you looking for more.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The short answer:&lt;/strong&gt; Mark a file as viewed and GitHub collapses it and advances a progress bar in the PR header; if the file changes later, it is automatically unmarked. That makes viewed state a reliable place-keeper within a review session on a large PR. Its limits are just as real: no folder-level marking, progress evaporates when the author force-pushes broadly, and the state records nothing about what you concluded, only that you looked.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What the GitHub mark file as viewed checkbox does
&lt;/h2&gt;

&lt;p&gt;The behavior, verified against &lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/reviewing-proposed-changes-in-a-pull-request" rel="noopener noreferrer"&gt;GitHub’s docs on reviewing proposed changes&lt;/a&gt;: after you finish reviewing a file, you can mark it as viewed and the file collapses. The progress bar in the pull request header shows how many files you have viewed. And the detail that makes the feature trustworthy: “If the file changes after you view the file, it will be unmarked as viewed.” That last rule matters. A place-keeper that lied about staleness would be worse than none, because you would skip files that changed under you. GitHub chose correctness over comfort here, and it is the right call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why place-keeping matters in large PRs
&lt;/h2&gt;

&lt;p&gt;Reviewing a large diff is fundamentally a working-memory problem: you are building a mental model faster than the file list can erode it. Every time you lose your place, you pay a re-orientation tax, scrolling to figure out what you have covered. &lt;a href="https://pyor.review/blog/why-are-pull-requests-so-hard-to-review" rel="noopener noreferrer"&gt;PRs are hard to review&lt;/a&gt; in large part because the diff view gives you no narrative structure, and on a big change the viewed checkbox is the one piece of state that survives a coffee break. Used with discipline, it turns an amorphous wall of files into a shrinking queue, which is also the core move in our guide to &lt;a href="https://pyor.review/blog/how-to-review-large-pull-requests" rel="noopener noreferrer"&gt;reviewing large pull requests&lt;/a&gt;: make progress visible, or fatigue will make the decisions for you. There is a secondary benefit that goes underappreciated: the progress bar is a cheap honesty check. If you approved a forty-file PR and the bar says nine files viewed, you know exactly what kind of review that was, and so do you the next time you are tempted to repeat it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pair it with the file filter
&lt;/h2&gt;

&lt;p&gt;Viewed state gets sharper when combined with the file filter dropdown, documented in &lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/filtering-files-in-a-pull-request" rel="noopener noreferrer"&gt;filtering files in a pull request&lt;/a&gt;. You can filter the diff by file extension, by lack of an extension, by code ownership, or by dotfiles, and you can temporarily hide deleted files or files you have already viewed. The combination is the workflow: filter to one slice of the change, read it, mark as you go, hide viewed files, and watch the remaining set shrink to zero. On a mixed PR, filtering to &lt;code&gt;.sql&lt;/code&gt; first, then source, then tests imposes at least a crude reading order on a list that is otherwise alphabetical. The file tree helps here too, with one documented quirk: it does not display if your screen is too narrow or if the PR contains only a single file, so on a laptop with a split screen you may be navigating by filter alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gaps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No folder-level marking.&lt;/strong&gt; Two hundred files of generated code under one directory means two hundred clicks. Filters can hide slices, but nothing marks a subtree as dealt with.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resets are all or nothing per file.&lt;/strong&gt; The auto-unmark is correct, but a rebase that touches every file wipes your progress wholesale, and nothing tells you what changed inside each unmarked file. That pain is the subject of our piece on &lt;a href="https://pyor.review/blog/re-reviewing-pull-requests-interdiff" rel="noopener noreferrer"&gt;re-reviewing with interdiffs&lt;/a&gt;: what you want after a push is the delta since your last read, not a fresh start.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No memory of conclusions.&lt;/strong&gt; Viewed records that you looked, not what you thought. Come back Monday and the checkbox cannot tell you which files worried you.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A workflow that gets the most out of it
&lt;/h2&gt;

&lt;p&gt;Within GitHub, the discipline that works: first sweep the trivial tail (lockfiles, snapshots, generated output) and mark it viewed immediately, so the progress bar reflects real work. Then filter by slice, read in dependency order as best you can, and leave unviewed anything you intend to revisit, treating the unviewed set as your literal queue. Comment as you read so conclusions live somewhere. Disclosure: the ceiling you eventually hit here, wanting reading order, grouping, and place-keeping that survives a force-push, is what we built &lt;a href="https://pyor.review/" rel="noopener noreferrer"&gt;Pyor&lt;/a&gt; for; it organizes the diff and scopes it per commit so your place is structural, not a row of checkboxes. But even with no new tools, viewed state used deliberately beats the default of scrolling and hoping.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7y2zok5w8jowfugfmshm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7y2zok5w8jowfugfmshm.png" alt="A file tree where two snapshot folders have been marked viewed with one click each, their rows dimmed, and the progress counter reads 14 of 18 files viewed." width="800" height="524"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Folder-level viewed: two snapshot folders marked viewed in two clicks, and the counter moves to 14 of 18 without touching a single file.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What happens when you mark a file as viewed on GitHub?
&lt;/h3&gt;

&lt;p&gt;The file collapses in the Files changed tab, and the progress bar in the pull request header updates to show how many files you have viewed. The state is yours alone; it does not signal approval to anyone else. If the file changes after you view it, GitHub automatically unmarks it as viewed so you know to look again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does viewed state persist if the author pushes new commits?
&lt;/h3&gt;

&lt;p&gt;Partially. Files untouched by the new commits stay marked, but any file that changed is unmarked automatically, per the GitHub docs. That reset is the honest behavior, since your earlier read no longer covers the new content, but it also means a rebase or wide-reaching push can wipe most of your progress in one stroke.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can you mark a whole folder as viewed?
&lt;/h3&gt;

&lt;p&gt;No. Viewed state is strictly per file; there is no folder-level checkbox in the Files changed tab. The closest workaround is the file filter dropdown, which can temporarily hide files you have already viewed, or filter by extension, code ownership, or dotfiles to shrink the visible set while you work through a directory.&lt;/p&gt;

</description>
      <category>github</category>
      <category>codereview</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>GitHub Review Requested Filter: Build a Real Review Inbox</title>
      <dc:creator>Othman Shareef</dc:creator>
      <pubDate>Fri, 02 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/pyor/github-review-requested-filter-build-a-real-review-inbox-26l9</link>
      <guid>https://dev.to/pyor/github-review-requested-filter-build-a-real-review-inbox-26l9</guid>
      <description>&lt;p&gt;The GitHub review requested filter is the closest thing GitHub has to a review inbox, and most developers use only its weakest form: glancing at the “Review requests” count on github.com/pulls. The search syntax underneath is considerably more capable. Every qualifier in this piece is checked against &lt;a href="https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests" rel="noopener noreferrer"&gt;GitHub’s documentation on searching issues and pull requests&lt;/a&gt;, and the last section is about what no query can give you: an actual sense of priority.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The short answer:&lt;/strong&gt; Five qualifiers do the real work: &lt;code&gt;review-requested:@me&lt;/code&gt; for everything waiting on you, &lt;code&gt;user-review-requested:@me&lt;/code&gt; for direct personal asks, &lt;code&gt;team-review-requested:&lt;/code&gt; for a team’s queue, &lt;code&gt;reviewed-by:@me&lt;/code&gt; for PRs you have touched, and &lt;code&gt;review:changes_requested&lt;/code&gt; for blocked PRs. Bookmark two or three combinations and you have a workable review inbox. What you do not get is ranking; every result looks equally urgent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The GitHub review requested filter family, verified
&lt;/h2&gt;

&lt;p&gt;The qualifiers that matter for a reviewer, straight from the docs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;review-requested:USERNAME&lt;/code&gt; matches pull requests where a specific person is requested for review. With &lt;code&gt;@me&lt;/code&gt;, that person is you.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;user-review-requested:@me&lt;/code&gt; matches pull requests that you have directly been asked to review, the personal asks as distinct from requests that reach you another way.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;team-review-requested:ORG/TEAM&lt;/code&gt; matches PRs with a pending review request to that team, which is your queue view when reviews route through a team alias.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;reviewed-by:@me&lt;/code&gt; matches pull requests you have reviewed, useful for finding threads you started and then lost track of.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;review:none&lt;/code&gt;, &lt;code&gt;review:required&lt;/code&gt;, &lt;code&gt;review:approved&lt;/code&gt;, and &lt;code&gt;review:changes_requested&lt;/code&gt; filter by review state, so you can find, say, every open PR sitting in changes-requested limbo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Direct asks versus team asks
&lt;/h2&gt;

&lt;p&gt;The distinction between &lt;code&gt;review-requested&lt;/code&gt; and &lt;code&gt;user-review-requested&lt;/code&gt; is the one worth internalizing. When someone types your username into the reviewers box, that is a personal ask with a social contract attached. When a CODEOWNERS rule or a team alias routes a PR to a group you belong to, you are one of several people who could take it. The docs define user-review-requested as the direct case, which is exactly why it deserves its own bookmark: those are the PRs where a specific human is waiting on you by name, and letting them age is how review requests &lt;a href="https://pyor.review/blog/stop-losing-review-requests" rel="noopener noreferrer"&gt;quietly get lost&lt;/a&gt;. The team query, by contrast, is a shared pool; the failure mode there is everyone assuming someone else will pick it up. The docs also list a further variant, &lt;code&gt;team-review-requested-user:USERNAME&lt;/code&gt;, which surfaces PRs with review requests to any team containing that user, handy for a lead who wants to see the load landing on one person through every team they belong to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watching the other side of the table
&lt;/h2&gt;

&lt;p&gt;Two more queries round out the picture. &lt;code&gt;reviewed-by:@me&lt;/code&gt; combined with &lt;code&gt;is:open&lt;/code&gt; shows PRs you already reviewed that have not merged, which is where re-review requests hide after an author pushes fixes. And &lt;code&gt;review:changes_requested&lt;/code&gt; scoped to your org surfaces every PR blocked on a rework cycle, the population most likely to be silently stuck. If your team has a turnaround expectation, these are the queries that make it inspectable; Google’s guidance on &lt;a href="https://google.github.io/eng-practices/review/reviewer/speed.html" rel="noopener noreferrer"&gt;review speed&lt;/a&gt; argues that slow turnaround is a team-level cost, and we have covered how to formalize that in &lt;a href="https://pyor.review/blog/code-review-slas" rel="noopener noreferrer"&gt;review SLAs&lt;/a&gt;. A query you can check is the difference between an aspiration and a practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the bookmark inbox
&lt;/h2&gt;

&lt;p&gt;The practical setup takes five minutes. Create bookmarks for three URLs built on github.com/pulls or global search:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mine, by name:&lt;/strong&gt; &lt;code&gt;is:open is:pr user-review-requested:@me&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Everything waiting on me:&lt;/strong&gt; &lt;code&gt;is:open is:pr review-requested:@me&lt;/code&gt;, optionally scoped with &lt;code&gt;org:YOURORG&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In flight:&lt;/strong&gt; &lt;code&gt;is:open is:pr reviewed-by:@me&lt;/code&gt; for the reviews you owe a second pass&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check the first one like you check messages; sweep the other two once or twice a day. This is crude, but it beats relying on notification emails that arrive interleaved with every other kind of GitHub noise. If you want one catch-all query for everything you touch, &lt;code&gt;involves:@me&lt;/code&gt; matches issues and PRs you created, were assigned, were mentioned in, or commented on; it is too broad to be an inbox, but it is a good weekly sweep for threads that fell through the narrower queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the filters stop helping
&lt;/h2&gt;

&lt;p&gt;Now the limits. Queries scope by org, but if you work across a company org, an open source org, and personal repos, no single query gives you a clean unified view without pulling in noise from all three. More fundamentally, search returns matches, not priorities: nothing in the result list tells you which PR is release-blocking, which is a two-minute approve, and which has been waiting three days. That ranking problem is a real capacity problem, and we have written about &lt;a href="https://pyor.review/blog/review-capacity-planning" rel="noopener noreferrer"&gt;treating review capacity as a planned resource&lt;/a&gt; rather than an overflow buffer. Bookmarked filters are the right floor. Just know that they hand you an unsorted pile, and the sorting is still your job. The other quiet limitation is that bookmarks are pull, not push: a query only helps when you run it. If your day fills up and the tabs stay closed, the queue ages invisibly, which is why teams that get serious about turnaround pair the queries with an explicit checking cadence, or with tooling that watches the queue for them instead of trusting willpower.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is the difference between review-requested and user-review-requested?
&lt;/h3&gt;

&lt;p&gt;Per the GitHub docs, review-requested matches pull requests where a specific person is requested for review, while user-review-requested:@me matches pull requests you have directly been asked to review. The narrower qualifier exists to separate personal asks from requests that reach you indirectly, so use user-review-requested when you only want the PRs with your name on them.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I see every PR waiting on my review across repositories?
&lt;/h3&gt;

&lt;p&gt;Search github.com/pulls or the global search with is:open is:pr review-requested:@me. That surfaces open pull requests where your review is requested across repositories you can access. Add org:YOURORG to scope it to one organization, and keep a second query with user-review-requested:@me for the direct, personal asks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can GitHub search rank review requests by urgency?
&lt;/h3&gt;

&lt;p&gt;No. Search returns matches sorted by things like recency, not by how urgent, blocking, or large a review is. Every result gets equal visual weight, so a one-line docs fix sits next to a release-blocking migration. Prioritization has to come from you, from team convention, or from tooling that layers a real queue on top of the raw query results.&lt;/p&gt;

</description>
      <category>github</category>
      <category>codereview</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>GitHub Code Review Shortcuts That Actually Save Time</title>
      <dc:creator>Othman Shareef</dc:creator>
      <pubDate>Wed, 30 Sep 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/pyor/github-code-review-shortcuts-that-actually-save-time-2157</link>
      <guid>https://dev.to/pyor/github-code-review-shortcuts-that-actually-save-time-2157</guid>
      <description>&lt;p&gt;Most GitHub code review shortcuts go unused because nobody knows they exist. That is a real cost: reviewers spend their day in the Files changed tab reaching for the mouse to do things the keyboard already handles. Every shortcut in this piece is verified against &lt;a href="https://docs.github.com/en/get-started/accessibility/keyboard-shortcuts" rel="noopener noreferrer"&gt;GitHub’s keyboard shortcuts documentation&lt;/a&gt;; anything we could not verify there is left out. The second half is the honest part: where faster keys stop mattering because the surface itself is the bottleneck.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The short answer:&lt;/strong&gt; Learn a dozen keys and the GitHub review loop gets noticeably faster: &lt;strong&gt;?&lt;/strong&gt; for the cheat sheet, &lt;strong&gt;T&lt;/strong&gt; to filter changed files, &lt;strong&gt;C&lt;/strong&gt; for the commits menu, &lt;strong&gt;I&lt;/strong&gt; to toggle diff comments, and Cmd+Enter family keys for submitting. But shortcuts optimize navigation, not comprehension. Once the PR is large enough that the problem is understanding, not clicking, no key binding rescues the web UI.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Press ? and read the map
&lt;/h2&gt;

&lt;p&gt;The one shortcut that teaches the rest: typing &lt;code&gt;?&lt;/code&gt; on a GitHub page opens a cheat sheet of the shortcuts available on that page. The set is contextual, which is why most people never discover the review-specific keys; they only ever see the sheet on the dashboard, if at all. Open it once on the Files changed tab of a real PR and you will find the review keys documented below. Two site-wide keys worth binding into muscle memory while you are there: &lt;code&gt;S&lt;/code&gt; or &lt;code&gt;/&lt;/code&gt; focuses the search bar, and &lt;code&gt;G&lt;/code&gt; then &lt;code&gt;P&lt;/code&gt; jumps to the repository’s Pull requests tab.&lt;/p&gt;

&lt;p&gt;Outside the diff, in regular code views, three more keys carry their weight. Pressing &lt;code&gt;T&lt;/code&gt; activates the file finder so you can fuzzy-type a path, &lt;code&gt;L&lt;/code&gt; jumps to a line number, and &lt;code&gt;B&lt;/code&gt; opens the blame view, which is often the fastest way to answer the review question “why does this code exist at all” without leaving the browser. They are not review shortcuts strictly speaking, but a review that never needs surrounding context is rare, and these are how you get to that context quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The GitHub code review shortcuts that earn their keep
&lt;/h2&gt;

&lt;p&gt;On the Files changed tab, the documented set is small but load-bearing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;T&lt;/code&gt; moves your cursor to the Filter changed files field. Type a path fragment, land on the file. This is the single highest-value key in a large diff.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;C&lt;/code&gt; opens the Commits dropdown to filter which commits are shown, which is how you scope the diff to one commit at a time instead of the whole branch.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;I&lt;/code&gt; shows or hides comments on diffs, useful when threads have buried the code they are arguing about.&lt;/li&gt;
&lt;li&gt;Click a line number, then Shift+Click another, to comment on a multi-line range instead of a single line.&lt;/li&gt;
&lt;li&gt;In a comment box, &lt;code&gt;Cmd+G&lt;/code&gt; (Ctrl+G) inserts a suggestion block, and &lt;code&gt;R&lt;/code&gt; quotes the text you have selected in your reply.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Batch the review, then submit once
&lt;/h2&gt;

&lt;p&gt;The submit keys mirror GitHub’s two commenting modes: &lt;code&gt;Cmd+Enter&lt;/code&gt; submits a standalone comment, while &lt;code&gt;Cmd+Shift+Enter&lt;/code&gt; on the Files changed tab submits a review comment, the kind that stays pending until you finish the review. Pending-first is the right default. Your comments remain private and editable until you submit, so a misreading you catch on file nine can be fixed on file two before the author ever sees it, and the author receives one notification instead of eleven. None of this is about typing speed; it is about turnaround. Google’s engineering guidance treats &lt;a href="https://google.github.io/eng-practices/review/reviewer/speed.html" rel="noopener noreferrer"&gt;review speed&lt;/a&gt; as a first-order health metric, and a reviewer who can enter, navigate, and batch a review without leaving the keyboard genuinely turns reviews around faster. Rounding out the set, the conversation page has its own documented keys: &lt;code&gt;Q&lt;/code&gt; opens the reviewer request menu, &lt;code&gt;A&lt;/code&gt; sets an assignee, and &lt;code&gt;L&lt;/code&gt; applies a label, so even the triage work around a review can stay on the keyboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where shortcuts hit the ceiling
&lt;/h2&gt;

&lt;p&gt;Here is the honest limit. Shortcuts compress the mechanical part of review: getting to the diff, getting to the file, getting the comment in. They do nothing for the expensive part, which is building a model of the change. When a PR spans forty files, the web UI offers you the same flat, alphabetical file list no matter how fast you filter it. There is no way to read by architectural layer, no persistent sense of place across visits, and jump-to-definition simply does not exist in a diff view. We have made &lt;a href="https://pyor.review/blog/stop-reviewing-code-on-github" rel="noopener noreferrer"&gt;the long version of this argument&lt;/a&gt; before, and the practical comparison of &lt;a href="https://pyor.review/blog/review-prs-locally-vs-browser" rel="noopener noreferrer"&gt;reviewing locally versus in the browser&lt;/a&gt; covers what an IDE gives you that no shortcut can.&lt;/p&gt;

&lt;h2&gt;
  
  
  The right way to think about it
&lt;/h2&gt;

&lt;p&gt;Learn the keys anyway. They are free, they compound over hundreds of reviews, and the cheat sheet takes two minutes to read. Just be clear about which problem they solve. If your reviews are slow because of clicking, shortcuts fix that this afternoon. If they are slow because &lt;a href="https://pyor.review/blog/how-to-review-large-pull-requests" rel="noopener noreferrer"&gt;the PRs are too large to hold in your head&lt;/a&gt;, the fix is structural: smaller units, commit-scoped reading, or a surface built for comprehension. Disclosure: that last category is why we build &lt;a href="https://pyor.review/" rel="noopener noreferrer"&gt;Pyor&lt;/a&gt;, which organizes the diff so the reading order makes sense rather than making you navigate an alphabetical list faster. Keys make a good surface quicker. They cannot make a flat one deep.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F47w0c3uw9fduunsfx7wn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F47w0c3uw9fduunsfx7wn.png" alt="Focus: Code mode: the pull request header, tabs and file rail are folded away and the split diff fills the window, with a thin bar at the top showing the hidden file count, search and an Exit Focus button with its shortcut." width="800" height="524"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Focus: Code, one shortcut away: the chrome folds and the diff fills the window, with the shortcut printed on the exit button.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How do I see all keyboard shortcuts on GitHub?
&lt;/h3&gt;

&lt;p&gt;Type ? on almost any GitHub page and a cheat sheet appears showing the shortcuts available for that specific page. The set changes by context: the Files changed tab has review shortcuts that do not exist elsewhere, and code views have their own navigation keys. The full list lives in the GitHub docs under accessibility keyboard shortcuts.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the fastest way to jump to a file in a pull request?
&lt;/h3&gt;

&lt;p&gt;On the Files changed tab, press T to move your cursor to the Filter changed files field, then type part of the path. In regular code views (outside a PR diff), T activates the file finder instead. Combined with the file tree on wider screens, this beats scrolling through a long diff by a wide margin.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should review comments be submitted one at a time or batched?
&lt;/h3&gt;

&lt;p&gt;Batched. Start a review with your first comment so subsequent ones stay pending and private until you submit, then send everything as one review. The author gets one coherent notification instead of a drip of emails, and you can revise earlier comments after later files change your understanding of the change.&lt;/p&gt;

</description>
      <category>github</category>
      <category>codereview</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
