← all articles

A Fix In One Change Is A Question About Its Sibling

A Fix In One Change Is A Question About Its Sibling

When a review finding is fixed in one change, go and ask the same question of its sibling. If two linked changes implement the same rule, the fix to the first does not make the pair consistent. It does the opposite. Until someone compares them again, you now have two versions of the rule, and the only thing keeping them honest is that nobody has noticed.

I watched this play out recently on a pair of closely related changes. A reviewer flagged how failures were being classified as timeouts. The author fixed it properly in the change under review: instead of looking only at the outermost error, the code now walked the whole chain of underlying causes to decide whether a timeout was really what had happened. That is a good fix. It is also the sort of fix that feels finished the moment the reviewer says "yes, that's better."

The catch was that a sibling change, already approved, did the same job for a different path. It had been reviewed on its own, found acceptable, and left alone. But when the two were set side by side, the sibling treated one extra condition as a timeout, a database-level cancellation, that the freshly fixed version did not. Neither was obviously wrong. They simply disagreed, and a caller would have seen a timeout in one place and an unrelated failure in the other for what was, from the user's point of view, the same thing happening.

Approval is a statement about a moment

The uncomfortable part is that the approved sibling was not a mistake. It was correct against the standard that existed when it was approved. The standard then moved, because a reviewer taught the author something about how that class of failure really behaves, and the approved change did not move with it.

I think we sometimes confuse "approved" with "settled." An approval is a statement about one diff at one point in time, judged against what everybody understood then. It is not a promise that the idea inside the diff stays correct as the surrounding understanding improves. When a finding changes what the team believes about a rule, every place that rule lives has quietly become a candidate for the same finding, including the places that already have a green tick.

This matters more than it sounds, because duplicated rules are rarely duplicated on purpose. Two changes end up sharing a contract because the work was split into manageable pieces, which is a sensible thing to do. Small changes are easier to review and kinder to the people reviewing them. But splitting the work does not split the rule. The rule is still one thing, and it is now written down twice, in two diffs that are read by people on different days, often with different amounts of context in their heads.

Review the set, not just the pieces

The practical change I've come to prefer is small. After fixing a finding, the author, and ideally the reviewer, asks where else the same rule is expressed, and then reads those places against the new version. Not to rewrite them. To compare them. Most of the time the answer is that they already agree, and the cost is a few minutes. Occasionally, as here, they don't, and the cost of finding out is a conversation instead of an incident.

Reviewing a related set together has another benefit that is easy to miss. In a separate group of three linked changes, reading them as a set for contract consistency surfaced a genuine bug that none of the individual reviews had caught: a value that was never initialised on the path where no configuration was supplied. Each change looked reasonable in isolation. It was the comparison between them, asking what each one assumed about the others, that made the gap visible. Isolation hides the places where one piece quietly depends on another being tidy.

None of this argues for giant changes. I'd still rather review three small things than one sprawling thing. The argument is that the unit of review and the unit of correctness are not always the same size. A reviewer sees a diff. The customer experiences a behaviour, and a behaviour is often spread across several diffs.

What it costs, and what it buys

There is a commercial reality here, because every extra round of comparison costs someone's time. Not every pair of changes deserves a formal cross-check. If two changes touch unrelated code and merely share an author, leave them alone. The trigger is a shared rule: a classification, a threshold, a status mapping, a definition of what counts as a failure. Those are the things users eventually experience as "the system's opinion," and inconsistent opinions are what turn into support tickets nobody can reproduce.

What it buys is trust in a quieter sense. When the same event is described the same way everywhere, the people operating the system can form accurate conclusions from what they see. When two paths describe the same failure differently, an operator reading a log is being asked to remember which path they are looking at before they can believe it. That is a small tax, but it is paid every time, by people who did not write either change.

So when a reviewer's comment lands and the fix is made, resist the pleasant feeling of being done. Ask what the comment was really about. If the answer is a rule rather than a line, the rule probably lives somewhere else too, and someone should go and check on its sibling.

Matthew Ratcliffe, software developer and architect, Ballarat
Senior Software Engineer & Architect

20+ years across the technology stack — from greenfield builds to brownfield rescues. Based in Ballarat, VIC, focused on AI, healthcare and high-risk data systems. Full resume →

Share your thoughts