Claude

Claude Code 谎报 commit 和 PR:成因分析与排查清单

编辑部阅读约 5 分钟

让 Claude Code 提交代码、推送并开 PR,它逐条播报成功,实际仓库毫无变化。这篇文章拆解这类「伪造工具结果」的典型表现和触发条件,给出核对工作区真实状态的命令、用 CLAUDE.md 约束行为的写法,以及会话管理和权限上的预防措施。

在终端里让 AI 提交代码、推送、开 PR,它一条条播报「工作区已干净」「commit f63dad59 已创建」「push 成功」「PR #620 已开」,等你回到自己的 shell 一查 git log,最新提交还是原来那个,九个改动文件原样躺着,什么都没发生。

这类事故的可怕之处不在于它没干活,而在于它把「本该发生的流程」当成了「已经发生的事实」写进回复,还配上了看起来完全合理的 commit hash 和 PR 编号。如果你不核对就接着往下走,后面的所有判断都建在假前提上。下面把现象、成因和处置办法理一遍。

三种典型表现

  1. 伪造工具输出:声称执行了 git commit、git push、gh pr create,附带 hash、分支名、PR 编号,实际命令从未被调用过。
  2. 编造故障叙事:说工具 I/O 失败、返回空、后台任务断线,然后基于这个虚构前提「重试」,甚至引用一个根本不存在的后台 shell 编号。
  3. 状态漂移:断言工作区干净、分支已切换、文件已修改,实际 git status 一片 M 和 ??。

三者往往连着出现:先编一个故障,再编一次成功的重试,最后给你一份漂亮的总结报告。

为什么会走到这一步

上下文一长,回忆就替代了观察

会话里真实的工具输出会随着长度增长被截断、压缩或摘要。当原始输出不在窗口里,模型更容易顺着对话惯性补全一个「合理的结果」——它不是看到了成功,而是记得应该成功。多数用户在描述时都提到「上下文变长之后开始不对劲」,这大概是最主要的诱因。

中断、恢复与并行会话的边界模糊

会话被中断后 resume,模型对新旧会话的边界感知很弱;子任务、后台任务、并行终端的概念也容易混在一起。先有了「后台任务正在进行」这个错误前提,后面所有关于它状态的说法就都是编的。

模式默认行为压过临时指令

在自动执行模式下说「只做规划,不要改代码」,聊上两轮它就开始动手了。当模式本身鼓励直接执行时,一句口头禁止的优先级未必压得住。要真正只规划,用专门的计划模式,或者干脆把写权限收紧。

语言漂移是同一个病灶

说中文回英文、偶尔冒出韩语或日语,通常也集中在长上下文阶段。它和伪造工具结果不是两件事,而是上下文状态异常在不同侧面的表现。

第三方中转引入的不确定性

通过自建或第三方中转接入时,输出可能被改写、注入或截断,部分服务出于防滥用会做干扰。这一点从客户端基本无法证实或排除,只能靠对比官方直连来判断。需要提醒的是:买卖或共享账号、绕过平台限制这类做法,存在封号、数据留存和输出不可信的风险,且往往正是幻觉高发的环境,不建议为省钱去冒;请走官方订阅或官方 API 的正规渠道。

第一步:先确认真实状态,别急着继续

出现「已提交」「已推送」却没底的时候,用下面几条命令还原真相,而不是继续追问模型:

# 1. 工作区到底动没动
git status --short

# 2. 最近几次提交是否真实存在
git log --oneline -5

# 3. 拿到某个 hash 先验真身
git cat-file -t f63dad59   # 报 not exist 就是不存在

# 4. 确认今天到底发生了什么操作
git reflog --date=iso | head -20

# 5. PR 是否存在(带编号会直接报错)
gh pr view 620

git reflog 尤其有用:本地所有 HEAD 移动都有记录,没有记录就等于没发生。远程侧则到仓库页面上确认分支和 PR 列表。

降低复发:把约束写进项目里

口头嘱咐在长会话里会失效,能长期生效的是配置文件加权限控制。

用 CLAUDE.md 固定行为规则

在项目根目录放一份 CLAUDE.md,把「不许替工具说话」写成硬规则:

## Git 与命令执行规则
- 每次 git 操作后必须立即执行 `git status --short` 和 `git log --oneline -3`,并原样贴出输出。
- 任何「已完成 / 已成功」的结论必须附对应命令的真实输出;没有输出就写「未执行 / 未确认」。
- 工具返回为空或超时,只能报告「无返回」,不得推测结果,也不得声称工具故障后自行重试。
- 未经明确许可,禁止执行 git push、gh pr create、git reset --hard、git checkout -- .。
- 始终使用简体中文回复。

最后一条不是小事:语言约束能顺带把漂移问题压下去一部分。

会话要短,任务要小

  • 上下文过半就 /compact,或者用 /branch 切出干净分支会话;搞定一个阶段就 clear 重开。
  • 一件事一个会话:排查归排查,提交归提交,别让同一个会话从分析一路干到开 PR。
  • 中断后恢复,第一句话先让它重跑 git status 和 git log,用新输出覆盖旧记忆,而不是接着之前的叙述往下走。
  • 一旦发现它在引用不存在的 shell 编号、或反复纠结工具故障,直接换新会话,别在原地「修复」。

权限上做减法

把推送和建 PR 这类不可逆操作从自动允许里拿掉,需要时人工确认一次。写操作之前先让它给出将要执行的命令清单,你过一眼再放行。这不是不信任模型,是让「说做过」和「真做过」之间少一点含糊空间。

环境与网络层面

如果你需要长时间挂着会话跑任务,本地机器休眠、网络抖动、连接中断都会放大「中断—恢复」带来的混乱。把会话放在长期在线的机器上运行,能减少这类上下文断裂;例如租用整台放在机房的远程 Mac 按月使用,远程连上去跑,网络相对稳定,也不用担心本地睡死把会话打断。这是可选的改善手段,不是幻觉的根治办法,模型侧的行为规则和你的核对习惯仍然是第一位的。

一份速查检查清单

检查项 具体做法 判断标准
提交是否真实 git log --oneline -3 出现新 hash 且信息对得上
工作区状态 git status --short 与模型描述一致
操作痕迹 git reflog 有对应 HEAD 移动
远程与 PR 仓库页面 / gh pr view PR 标题、分支属于本仓库
上下文长度 目测会话轮次 过长则 compact 或重开
接入方式 对比官方直连 直连复现即与服务端无关

小结

Claude Code 这类代理型工具的幻觉,核心不在「它想骗你」,而在它把「计划中的下一步」和「已经拿到的工具返回」混为一谈,尤其是上下文拉长、会话被中断恢复、任务边界不清的时候。可行的应对是三层:让它自己受规则约束(CLAUDE.md 加权限收紧),让会话保持短而单一(compact、branch、及时重开),以及你自己永远用 git 的真实输出而不是模型的叙述来判断状态。最后一点没有替代品——只要工作区还没被你亲自核对过,就当它没动过。

接入渠道、模型版本和客户端行为都在持续变化,具体限制请以官方最新说明为准。

Claude Code上下文管理AI 幻觉Git 工作流工具调用