这次遇到了一个有点好笑的问题:代码已经推送到 GitHub,PR 页面却像什么都没发生过,始终显示旧的提交列表。
最后的解决办法很朴素:把 PR 关掉,再重新打开。提交就同步了,随后也正常合进了 main。
不过,在点这两个按钮之前,最有用的一步是先确认:到底是代码没有推上去,还是 PR 没有跟上分支。
分支已更新,页面却只有旧的 8 个提交
当时的 PR 是 #76。页面显示 8 个提交,最后一个是 fab9342,并且提示:
No conflicts with base branch
Merging can be performed automatically.看起来可以合并,但最新的两次修改没有出现在列表中。
最初怀疑是本地只做了 commit,没有 push。这个猜测很常见,也很好验证:
git push origin HEAD结果只有一句:
Everything up-to-date这说明这次推送没有新的分支更新需要发送。继续重复同一条命令,也不会凭空产生一次新的更新事件。
接着核对本地 HEAD 和远端分支,发现它们都已经到了 6ac0bfd57。因此,至少在这次核对时,“代码没推上去”已经解释不了现象。
把远端分支和 PR 引用放在一起看
真正让问题变清楚的是这条命令:
git ls-remote origin refs/heads/codex/game-user-config-token refs/pull/76/head refs/pull/76/merge当时实际返回:
6ac0bfd5768692df9c601c663a6609aff1424814 refs/heads/codex/game-user-config-token
fab93428ea3256cd1bd58bc07efee9d38c370eef refs/pull/76/head
46300399e963f736b8a54903a7be6981e9a36ce3 refs/pull/76/merge前两行已经足够说明问题:远端分支到了新提交,PR 的 head 引用却仍停在旧提交,恰好与页面显示的最后一个提交一致。
第三行的 merge 引用单独列出作记录,它不应该被拿来与源分支 HEAD 直接比较是否相等;这次判断同步问题,依据的是前两行。
这时就不能再把问题简单归因于浏览器没刷新了:GitHub 对外提供的 PR 引用本身也没有跟上分支。
GitHub 在关于 PR 更新处理延迟的公告中说明,推送到 PR 分支的提交有时会比通常情况花更长时间处理,在进入提交列表前会显示提示。这个说明与当时的现象相符,但它没有告诉我这一次具体卡在了哪个内部步骤。
没有服务端日志,就无法进一步确认是任务积压、缓存失效,还是别的内部状态问题。能确认的是分支与 PR 引用不一致。
关闭,再重新打开
找到的GitHub 社区同类问题讨论提到了关闭再重新打开 PR,以及推送空提交等处理办法。这些是其他用户的恢复经验,不是保证成功的官方修复接口。
我这次选择了影响更小的操作:
- 关闭 #76,保留原分支。
- 重新打开同一个 PR。
- 确认页面恢复显示最新提交,再进行合并。
这次确实有效,最终修改已经进入 main。没有删除分支,没有重建 PR,也没有为了触发处理额外塞一个空提交。
这里的“重新打开”指关闭后点击 Reopen pull request,不是把浏览器标签页关掉再打开。
我没有在恢复后再保存一份 ls-remote 输出,因此这里不补写一段看似完整的“修复后日志”。恢复结果来自实际页面同步和后续合并成功。
下次遇到,先检查哪一层没有跟上
这次排查最值得留下的是三个检查点:
- 本地 HEAD:修改究竟提交到了哪里。
- 远端源分支:代码是否已经推送到 PR 使用的分支。
- PR 的 head 引用:GitHub 的 PR 是否跟上了该分支。
可以按自己的分支名和 PR 编号执行:
git rev-parse HEAD
git ls-remote origin refs/heads/feature/my-change refs/pull/123/head如果本地和远端分支不同,先处理推送问题。如果远端分支与 PR head 不同,就有了比页面提交数量更直接的证据。
页面显示“没有冲突”和“可以自动合并”,也不能代替这一步核对。至少在本次故障里,这两句话和旧的提交列表同时存在。
本地合并后直接推送 main 也是当时考虑过的路径,但最后没有用到。既然关闭再重新打开就恢复了,就继续沿原来的 PR 完成合并。
这次没有找到 GitHub 内部停滞的根因,只找到了一个有证据支持的定位方式,以及一个在本次故障中有效的恢复动作。Git 的分支已经到站,PR 还停在上一站;关掉再打开,终于追上了。