TL;DR(30 秒解法): 别 accept。在 diff 视图里按文件逐个 reject(如果已经 accept 了,就在 chat 时间线上点 Restore Checkpoint),然后给 Composer 发一条 prompt:“这次改动太大没法安全 review。先不要改代码。把它拆成 3-5 个小 PR,每个列出:标题、涉及文件、预估行数、依赖关系。” 然后挨个执行。最后在 .cursor/rules/ 里加一条限制 diff 大小的规则,从根上不让它再发生。
Composer 一次 turn 给你 30 个文件 / 2000 行 diff,review 面板里红绿一片,滚到底也看不清哪些是核心改动、哪些是”路过顺手”清理。测试都过了你还是不放心,因为没人能一口气负责任地 review 2000 行 AI 改动。这通常不是模型出错,而是你给的 prompt 太宽 + Composer 默认一次包圆。
止血方式不是更努力 review,而是 reject 后让它拆。
你属于哪一类
绝大多数超大 diff 都能归到下面六类原因之一。先对号入座,再跳到对应修法。
| # | 原因 | 最快的判断信号 |
|---|---|---|
| 1 | 任务粒度太大 | prompt 里有 “system”、“module”、“everything”、“全部” |
| 2 | 功能改动混进顺手清理 | diff 里既有新功能,又有 rename / reformat |
| 3 | Agent mode 跨文件连环传播 | 消息里一长串 read / edit 工具调用链 |
| 4 | 简单任务上了重写型大模型 | 模型说”我把它重写得更现代了” |
| 5 | 规则里没限制 diff 大小 | .cursor/rules/ 里没有限制改动大小的规则 |
| 6 | 让它一次给出”完美方案” | prompt 里有 “best practice”、“clean architecture”、“完美” |
1. 任务粒度太大,本该分多次 Composer
“重构 auth 系统” 这种 prompt 必然出大 diff。模型尽力执行,把鉴权、session、API 中间件、tests、错误处理全改了。
如何判断: 扫一眼 prompt 里有没有 “system”、“module”、“everything”、“全部” 这种词。
2. Composer 把功能改动和顺手清理混了
模型实现新功能时,路过看到”这命名好丑”、“这函数好长”,顺手就重构了。你 review 时很难区分哪些是必要的、哪些只是它的审美。
如何判断: diff 里既有新功能代码,又有 rename / extract function / reformat 这类改动。
3. Agent mode 多步连环、跨文件传播
Agent 一边改一边发现还得改另一处,连环 5 个 tool call 后改的文件数翻了 3 倍。
如何判断: 把 Composer 这条消息展开,看是不是一长串 read_file / edit_file 调用链。
4. 简单任务上了重写型大模型
前沿大模型在 agent 模式下倾向”大刀阔斧”。截至 2026 年 6 月,Cursor 的模型选择器里包含 Composer 2.5(Cursor 自家的快速 agent)、Claude Sonnet 4.6 和 Opus 4.7、GPT-5.5、Gemini 3.1 Pro。其中推理更重的 Opus 4.7、GPT-5.5 最容易把 100 行的 patch 变成 800 行的”现代化重写”。日常的快速内循环用 Composer 2.5,它更贴近你给的 scope;只在遇到真正难的问题时才切到 Opus 4.7。
如何判断: 模型说”我把它重写得更现代了”或”我顺手清理了一下” = 危险信号。
5. 项目规则里没限制 diff 大小
模型默认没有 diff size 上限。如果你不告诉它把改动控制小一点,它就照训练时学到的”完整方案”输出。注意:单文件根目录 .cursorrules 已从 Cursor 0.43 起被弃用,改用 .cursor/rules/*.mdc。旧文件目前还能用,但新规则应放到新位置。
如何判断: 看 .cursor/rules/ 下(或遗留的根目录 .cursorrules)有没有任何规则提到 “max diff”、“small”、“reviewable”。
6. 让模型一次给出”完美方案”
prompt 写成”按业界最佳实践重构这个模块”,模型会理解成”输出一个完整的、符合最佳实践的版本”——也就是大 diff。
如何判断: prompt 里有 “best practice”、“clean architecture”、“完美” 字样。
动手前先确认
- 确认问题出在哪个入口:Composer、Cmd+K(行内编辑)还是 chat。Cmd+K 因为只作用于选区,一般不会出大 diff。
- 先不要 accept。如果改动还停在 review 面板里,就让它停着。如果已经 accept,仍可通过下面的
Restore Checkpoint找回。 - 无论如何先跑
git diff > /tmp/big-diff.patch留一份证据。 - 记下 Cursor 版本(Cursor 菜单 -> About)、选择器里的当前模型、是否开了 agent 模式。
需要收集的信息
- 触发这个 diff 的完整 prompt。
git diff --stat输出(每个文件的行数)。- Composer 这条消息的 tool call 链截图(看是 1 次还是 N 次连环)。
- 当前模型和模式。
- 你的
.cursor/rules/文件(或遗留的根目录.cursorrules),以及里面有没有限制 diff 大小的条款。
最短修复路径
按”先拆,再改协作流程”的顺序来。
Step 1:Reject,不要 accept
review 面板里你可以逐个文件 reject,也可以一次全 reject。如果 Composer 改对了四个文件、只错了一个,就用逐文件 reject;否则整批 reject。别被”可惜”心理推动去 accept——大 diff 一旦 accept,cleanup 成本远高于 reject 重做。
已经 accept 了? 打开 chat 时间线,找到这一 turn 之前那条消息,点 Restore Checkpoint。Cursor 在每次 agent 改动前都会自动打一个 checkpoint,所以它会回滚 AI 的改动、同时保留你手动的修改。注意(2026 年 6 月):checkpoint 可能漏掉新创建的文件,并且会话结束或重命名文件夹后会被清掉,所以每次跑 agent 前先做一次真正的 git commit 仍是最稳的兜底。
Step 2:让 Composer 自己拆方案
新发 prompt:
The previous proposal is too large to review. Do NOT change code yet.
Instead:
1. Split it into 3-5 smaller PRs.
2. For each PR, list:
- title (one line)
- files touched
- estimated diff size (lines)
- what it accomplishes
- dependencies on other PRs in this list
3. Order them so the riskiest is last.
得到 5 条小 PR 清单后挨个评估。
Step 3:单独执行每个小 PR
Now implement PR #1 only. Stay within the listed files. Do not start PR #2.
apply → run tests → commit → 切下一条。每条都是独立可 revert 的。
Step 4:清理 vs 行为变更分开
如果某条 PR 既改逻辑又 reformat,让模型再拆:
Split PR #2 again: one PR for "rename foo to bar" (mechanical), one PR for "add retry logic" (behavioral).
Apply the mechanical one first; review separately.
Step 5:用 Project Rule 固化 diff 上限
旧的根目录 .cursorrules 文件已从 Cursor 0.43 起被弃用。把规则放到 .cursor/rules/ 下、做成带 frontmatter 的 .mdc 文件,这样它能进版本控制、每次都自动加载。新建 .cursor/rules/small-diffs.mdc:
---
description: Keep AI diffs small and reviewable
alwaysApply: true
---
- Default to small, reviewable diffs (at most ~200 lines per response).
- When a task seems to require a larger change, STOP and propose a split plan instead of editing.
- Never combine a refactor or rename with a behavioral change in one diff.
- Always state the estimated diff size before generating code.
alwaysApply: true 会把这条规则注入每次 Composer 会话。(如果你还留着遗留的根目录 .cursorrules,同样的几条目前也能用,但建议迁移过去。)
Step 6:如果真的必须 apply 大 diff
有些场景确实拆不开(比如生成器跑出来的输出)。apply 前先 commit 一次干净基线,accept 改动后立即再 commit,附一条类似 feat: bulk codegen output, do not review line-by-line 的 message。这样 revert 就是单条 git commit,而不用手动一点点拆解。
怎么确认已经修好
- 同一个 prompt 重跑一次,确认模型现在主动给出”拆分方案”,而不是直接甩 2000 行。
- 对每个已实现的 PR 跑
git diff --stat,确认它都贴近你设的行数预算。 - 让队友拿同样的 prompt 跑一遍,验证规则是从共享的
.cursor/rules/加载的,而不只是你本地的配置。 - 每条拆出来的小 PR 都能独立通过 CI 和 review,并能用一条
git revert干净回滚。
如果还是没修好
- 把 prompt 缩到一句话 + 单文件 + 单目标。
- 确认规则确实加载了:在 chat 里
@引用规则文件,或检查.cursor/rules/small-diffs.mdc是否写了alwaysApply: true且 frontmatter 合法(该目录下纯.md文件会被忽略)。 - 回滚最近一次规则改动,确认改变行为的是规则而不是模型本身。
- 在 forum.cursor.com 搜 “composer split PR”,附上你的 prompt、模型和 diff 大小。
- 从
View -> Output -> Cursor抓日志,贴到 Bug Reports 板块。
预防建议
- prompt 模板里固定加一句:“先报 diff 行数预估;如果超过 200 行,先提拆分方案再写代码。”
- 单文件改动默认用行内编辑(Cmd+K)或 chat;只在确实需要 multi-step 时才手动切到 agent 模式。
- 每个 Composer 任务一条 feature branch,每个小步骤后做一次
gitcommit。 - 已知的大重构,用 Claude Code 这类 CLI agent 跑、按文件显式 scope,而不是一次 Composer turn。同样的 scope 纪律可参考 Claude Code 重构范围太大。
- 团队 PR 规则:AI 生成的 diff 超过 300 行,不拆不接受 review。
常见问题
能只 reject 部分文件、而不是整个 diff 吗? 可以。review 面板支持逐文件 accept/reject。如果 Composer 改对了四个文件、只搞坏了第五个,就 accept 那四个、reject 那一个。这通常比全部 reject 再重新 prompt 更快。
我已经把大 diff accept 了,还能撤销吗?
在 chat 时间线上,找到那一 turn 之前的消息,点 Restore Checkpoint。Cursor 在每次 agent 改动前都会自动打 checkpoint,所以它会回滚 AI 的改动、保留你手动的修改。但它可能漏掉新创建的文件,所以如果你事先 commit 过,用 git reset 或 git revert 更可靠。
.cursorrules 还是 .cursor/rules/,该用哪个?
用 .cursor/rules/*.mdc。单文件根目录 .cursorrules 已从 Cursor 0.43 起弃用,Cursor 计划最终彻底移除它。新格式能进版本控制、支持 glob 范围匹配,还支持 alwaysApply,让限制 diff 大小的规则在每次会话都生效。
哪个模型给的 diff 最小? 截至 2026 年 6 月,在快速内循环里,Cursor 自家的 Composer 2.5 最贴近你给的 scope。Opus 4.7、GPT-5.5 这类更重的推理模型在难题上方案更强,但更容易大刀阔斧重写,所以只在真正难的任务上才用它们。
那干脆把 agent 模式彻底关掉行不行? agent 模式本身是处理多步骤工作的正确工具,问题在于把它用在了不需要跨文件连环的任务上。单文件改动默认用行内编辑(Cmd+K),需要时才有意识地切到 agent 模式,而不是顺手就开。