# 给分支做工程评审的那一步,报了一句大实话:"没有可评审的改动,main...HEAD 是空的" > 给分支做工程评审的那一步,报了一句大实话:"没有可评审的改动,main...HEAD 是空的"。第一反应是重跑,停一下想深一层:这不是评审坏了,是评审的前提没了。 这种状态为什么能 - Canonical page: https://obelisk.club/blog/build-log-1291 - Author: Peter Zhang - Published: 2026-10-11 - Tags: build-log 给分支做工程评审的那一步,报了一句大实话:"没有可评审的改动,main...HEAD 是空的"。第一反应是重跑,停一下想深一层:这不是评审坏了,是评审的前提没了。 这种状态为什么能一路隐形、直到评审才显形:本该产出改动的那一步可以"正常结束"——没有报错、没有提交、也没有留下任何"我被什么挡住了"的记录。空 diff 就是这种"既无改动也无说明"的唯一可见症状,而它只在第一个真正去读 diff 的环节才暴露。反过来想更后怕:如果评审在空 diff 上返回通过,那就是一个"什么都没评审"的绿——和 "Executed 0 tests" 的绿是同一种绿。 修这类问题的顺序是承重的: 1. 先把拒绝读成对上游的证据,而不是对本次尝试的判决。main...HEAD 为空只有三种可能:改动从未提交、提交落在了别的分支、分支已被合并或变基掉。三种可能对应三个不同的修复,重跑评审一个也修不了。 2. 再去找改动实际在哪:对比 HEAD 与 main,确认分支是否早已合入,回查产出改动的步骤到底留下了什么。定位到生产者,修生产者。 3. 最后把守卫放到派发处:评审开跑前先数 diff 里的提交数,为零就直接拒;并且要求任何"产出改动"的步骤结束时留下两样之一——要么改动,要么写明被什么挡住。"既没有改动也没有 blocker"的结束是最坏的一种:从内部读像成功,从下游读是一个解释不了的空洞。 一分钟自检:在你的门禁真正消费的那个分支上跑 `git rev-list --count main...HEAD`。如果是 0,你的评审正在评审"无"——先问提交去了哪,再谈重跑。