@@ · reading order @@

Review pull requests in dependency order, not alphabetical

Othman Shareef · July 15, 2026 · 6 min read

Open any pull request on GitHub and the changed files come in one order: alphabetical, by path. The file tree in the sidebar folds them into folders, but sorts alphabetically within it, so it is no more dependency-aware than the flat list. It is a tidy order, and it is the wrong one. Alphabetical sorting is a property of the filesystem, not of the change. It tells you nothing about what depends on what, so you routinely read a file that calls a function defined three files down, before you have seen that function. Dependency order fixes exactly this.

Why alphabetical order fights you

A reviewer’s hardest job is building a mental model of an unfamiliar change, and that reconstruction is where review time goes. Alphabetical order actively works against it. Consider a feature touching api/handlers.ts, lib/validate.ts, and lib/schema.ts. The handler imports the validator, the validator imports the schema, so understanding flows schema to validator to handler. Alphabetical order serves them handlers, then schema, then validate: you meet the consumer first, hit a call into code you have not read, scroll away to find it, lose your place, and come back. Every forward reference is a context switch, and a big PR is full of them.

What dependency order does instead

Dependency order is a topological sort of the change. It reads the import statements in each changed file, keeps the edges that point at other files in the same PR, and orders the files so a dependency always comes before the file that uses it. In practice that means the same reading order a good author would walk you through: here is the new type, here is the helper that produces it, here is the function that calls the helper, here is the endpoint that ties it together. Each file, by the time you reach it, only references things you have already seen. The mental model accretes instead of thrashing.

It is the file-level version of a discipline we already recommend for commits. Atomic commits let a reviewer read a change step by step in a sensible order; dependency order does the same for the files within a single view, without asking the author to do anything.

This is how understanding actually works

You cannot understand a function that calls parseConfig() until you know what parseConfig() does. Read bottom-up (definitions before uses) and every line lands against context you already have. Read top-down (uses before definitions) and you are constantly deferring judgment, holding half-understood calls in working memory until you finally reach what they resolve to. The second mode is how alphabetical order makes you review, and it is exhausting on exactly the large, multi-file PRs that are hardest to get through. Ordering the files by dependency is a small change that removes a whole category of that load.

How Pyor computes it

This is a feature we build (disclosure: we make Pyor), and the part worth saying plainly is that it uses no AI. Dependency order is a deterministic pass over the import graph: Pyor parses the import and require specifiers in the changed files, resolves the ones that point at other files in the PR (relative paths exactly, aliased and workspace imports by matching the PR’s own files), and topologically sorts the result. Files with no resolved in-PR dependency keep their original position, and import cycles fall back to the original order, so the arrangement is always stable and explainable. Same PR, same order, every time. It is one grouping dimension you switch on; there is nothing to configure.

That determinism is the point. It fits the same principle behind where AI belongs in review: when a task has a correct, checkable answer (the import graph is right there in the code), compute it exactly rather than asking a model to guess. The reviewer gets a better reading order without a summary to second-guess.

Where it helps most, and where it does not

Dependency order earns its keep on cohesive, multi-file changes where the files actually import one another: a new feature, a refactor, a module split. On a PR of unrelated edits with no shared imports there is no graph to exploit, and the order falls back to the original one rather than inventing structure that is not there. It also reads the import graph most completely once full file contents are loaded; from the diff alone it sees only the import lines that changed. Honest tool behavior is a fallback, not a guess, and that is what this does when the signal is thin.

None of this replaces the reviewer’s judgment. It just stops making you fight the file list to apply it. Read the code in the order it was built, and the review gets easier for the most boring possible reason: you stop scrolling backward.

Frequently asked questions

What is dependency order in code review?

Dependency order arranges a pull request's changed files so each file comes after everything it imports from other files in the same PR. The pure exporters (new helpers, types, utilities) sort to the top and the entry points that consume them sort to the bottom, so you read each file only after seeing what it builds on.

Isn't alphabetical file order fine for small PRs?

For a one or two file change, order barely matters. The cost shows up on multi-file changes where files import each other: alphabetical scatters a helper and its callers to opposite ends of the list, so you read a consumer before the thing it depends on and have to jump. Dependency order removes those forward references.

Does dependency order use AI?

No. It is a deterministic reading order computed from the import graph: the tool parses import statements in the changed files, resolves the ones pointing at other PR files, and topologically sorts. Files with no in-PR dependency keep their original position and cycles fall back to the original order. Same input, same order, every time.

← All posts