前言上一篇文章中从源码角度找到了ocr review的命令入口。当用户执行ocr review程序会从cmd/opencodereview/main.go进入命令分发逻辑然后进入runReview(args[1:])接着会调用parseReviewFlags(args)解析命令行参数。也就是说第二篇主要解决的是ocr review 是从哪里启动的这一篇继续往下学习一个更基础、也更关键的问题ocr review 为什么知道我改了哪个文件在第一篇中执行过ocr review--preview终端输出Preview: 1 file(s) changed | 7 -1 Will review (1): [M] s01/src/user.js当时只是知道OpenCodeReview 识别到了 s01/src/user.js 的变更。但是还不清楚[M] 是什么意思 7 -1 是怎么来的 为什么它知道要审查这个文件 ocr review --preview 和 git diff 有什么关系所以本文就围绕这些问题学习 Open Code Review 的核心输入Git Diff。一、本篇学习目标本文主要解决下面几个问题1. 什么是 Git diff 2. 为什么 ocr review 依赖 Git diff 3. git status、git diff 和 ocr review --preview 有什么关系 4. [M] 表示什么 5. 7 -1 是怎么统计出来的 6. 为什么 Git diff 中会出现 -1 7. ocr review --preview 做了什么这一篇关注Open Code Review 是如何识别本次代码变更的二、为什么先学习 Git Diffocr review和ocr scan不一样。ocr scan更偏向全量扫描目录或文件而ocr review的核心是审查本次代码变更。也就是说ocr review首先要知道这次改了哪些文件 每个文件新增了多少行 每个文件删除了多少行 哪些文件需要审查 哪些文件应该排除这些信息主要来自 Git。所以可以先简单理解为Git diff 是 ocr review 的输入。如果没有 Git diffocr review就不知道本次要审查哪些代码变更。这也是为什么 Open Code Review 适合用于本地未提交变更审查 commit 审查 分支差异审查 Pull Request 审查因为这些场景的本质都是比较两份代码之间的差异。三、准备一个代码变更为了方便观察 Git diff在练习项目中修改了s01/src/user.js本次新增了一个函数functionupdateUserEmail(db,userId,email){db.query(UPDATE users SET email email WHERE id userId);returntrue;}并且在module.exports中导出了它module.exports{getUserName,login,buildUserQuery,fetchUser,deleteUser,updateUserEmail};这个函数写得比较简单而且包含明显的问题1. SQL 字符串拼接 2. 没有参数化查询 3. 没有错误处理 4. 总是 return true。不过这一篇不分析代码审查结果只分析 Git diff 和 preview 输出。四、查看当前 Git 状态首先进入练习项目目录cd D:\agent\open-code-review-main\ocr-practice-demo然后执行git status--short输出结果中可以看到M s01/src/user.js这里的M表示文件被修改了。也就是说Git 已经检测到s01/src/user.js 发生了修改。注意这里的M是 Git 原生输出中的文件状态。后面ocr review --preview中看到的[M]也是类似含义表示Modified文件被修改。五、查看变更文件状态git diff --name-status接着执行gitdiff--name-status输出类似M s01/src/user.js这条命令只关心哪些文件变了 这些文件是什么状态其中M Modified修改文件 A Added新增文件 D Deleted删除文件 R Renamed重命名文件所以这次输出M s01/src/user.js表示s01/src/user.js 是一个被修改的文件。这和ocr review --preview中的[M] s01/src/user.js是对应的。六、查看新增和删除行数git diff --numstat继续执行gitdiff--numstat输出结果7 1 s01/src/user.js这三个部分分别表示7 新增行数 1 删除行数 文件路径所以这次变更可以理解为src/user.js 新增了 7 行删除了 1 行。这个输出可以帮助我们验证ocr review --preview中7 -1的含义7 insertions → 7 1 deletion → -1需要注意这里是用git diff --numstat辅助理解 Preview 输出并不表示 OpenCodeReview 源码中直接调用了git diff --numstat。从源码角度看OpenCodeReview 会先获取 unified diff 文本再解析 diff 内容统计每个文件的新增行和删除行。七、查看 diff 统计git diff --stat继续执行gitdiff--stat输出结果.../src/user.js | 8 - 1 file changed, 7 insertions(), 1 deletion(-)这条输出更适合人阅读。它说明1 个文件发生变化 新增了 7 行 删除了 1 行。其中7 insertions()表示新增 7 行。1 deletion(-)表示删除 1 行。这和前面的git diff --numstat、ocr review --preview是一致的。可以整理成下面的对应关系命令输出含义git diff --name-statusM s01/src/user.js文件被修改git diff --numstat7 1 s01/src/user.js新增 7 行删除 1 行git diff --stat1 file changed, 7 insertions, 1 deletion变更统计ocr review --preview[M] src/user.js 7 -1Open Code Review 预览审查范围八、查看具体 diff 内容接下来执行gitdiff可以看到具体代码差异diff --git a/s01用最小 Demo 跑通 AI 代码审查/src/user.js b/s01用最小 Demo 跑通 AI 代码审查/src/user.js index 1445e1f..f9f2188 100644 --- a/s01/src/user.js b/s01/src/user.js -33,10 33,16 function deleteUser(db, userId) { return true; } function updateUserEmail(db, userId, email) { db.query(UPDATE users SET email email WHERE id userId); return true; } module.exports { getUserName, login, buildUserQuery, fetchUser, - deleteUser deleteUser, updateUserEmail };这段 diff 是理解7 -1的关键。其中这一行叫做 hunk header -33,10 33,16 function deleteUser(db, userId) {可以简单理解为-33,10 表示旧文件从第 33 行开始共 10 行 33,16 表示新文件从第 33 行开始共 16 行。这类行号信息后面会非常重要因为 Agent 最终生成的code_comment需要定位到具体文件和具体代码行。九、理解 diff 中的和-在 Git diff 中 表示新增行 - 表示删除行例如下面这几行function updateUserEmail(db, userId, email) { db.query(UPDATE users SET email email WHERE id userId); return true; } 这些都是新增行。所以它们会被统计到7而这一行- deleteUser表示旧版本中原来是deleteUser后来变成了 deleteUser, updateUserEmail也就是deleteUser,updateUserEmail所以 Git 认为旧的 deleteUser 这一行被删除 新的 deleteUser, 这一行被新增 updateUserEmail 这一行也被新增。这就是为什么只是加了一个逗号却会出现-1十、执行ocr review --preview接下来执行 Open Code Review 的预览命令ocr review--preview输出结果[ocr] A new version (v1.7.0) is available. Run to update: npm i -g alibaba-group/open-code-review1.7.0 Preview: 1 file(s) changed | 7 -1 Will review (1): [M] s01/src/user.js真正重要的是Preview: 1 file(s) changed | 7 -1以及Will review (1): [M] s01/src/user.js这说明 Open Code Review 识别到了1 个文件发生变化 新增 7 行 删除 1 行 这个文件会被纳入审查 文件状态是 Modified。十一、把 Git 输出和 OCR Preview 对应起来现在可以把 Git 原生命令和 Open Code Review Preview 输出对应起来。1. 文件数量对应git diff --stat输出1 file changedocr review --preview输出Preview: 1 file(s) changed二者对应Git 检测到 1 个文件变化 ↓ OCR Preview 显示 1 file(s) changed2. 文件状态对应git diff --name-status输出M s01用最小 Demo 跑通 AI 代码审查/src/user.jsocr review --preview输出[M] s01/src/user.js二者对应Git 中的 M ↓ OCR Preview 中的 [M]含义都是Modified文件被修改。3. 新增删除行数对应git diff --numstat输出7 1 s01用最小 Demo 跑通 AI 代码审查/src/user.jsocr review --preview输出7 -1二者对应7 insertions ↓ 7 1 deletion ↓ -1所以ocr review --preview展示的7 -1本质上来自本次 Git diff 的新增和删除行数统计。十二、ocr review --preview的作用通过前面的对比可以发现ocr review --preview的作用是在不真正调用 LLM 的情况下 提前告诉我这次会审查哪些文件。它可以帮助我在正式执行审查前确认几个问题1. 当前是否有 Git 变更 2. 哪些文件会被审查 3. 哪些文件被排除 4. 每个文件的变更规模是多少 5. 文件状态是新增、修改还是删除。这一步非常重要。因为正式执行ocr review会调用 LLM可能产生 token 消耗和等待时间。所以在正式 review 前先执行ocr review--preview可以避免一些问题。例如不小心审查了无关文件 忘记忽略生成文件 把 JSON 结果文件也纳入了 review 当前其实没有代码变更 审查范围比预期大很多。因此使用习惯是先执行 ocr review --preview 确认范围没问题 再执行 ocr review十三、为什么git diff和 Preview 有时对不上本文示例中的修改是未暂存的 tracked 文件所以git diff、git diff --numstat和ocr review --preview的结果可以很好地对应起来。但在真实项目里有时你会发现git diff 看不到某些文件 ocr review --preview 却能看到。原因是 OpenCodeReview 的 workspace 模式不只是简单执行裸git diff。从源码逻辑看workspace 模式会处理两类变更1. tracked 文件变更通过 git diff HEAD 获取相对 HEAD 的变更 2. untracked 文件变更通过 git ls-files --others --exclude-standard 找到未跟踪文件并手动构造 diff。这意味着如果文件已经 git add普通 git diff 可能看不到因为它默认比较工作区和暂存区 如果文件是 untracked普通 git diff 也看不到因为它还没有进入 Git 跟踪 但 ocr review --preview 仍然可能把它们纳入审查范围。所以在对照 OCR Preview 时更接近的理解方式是tracked changes: git diff HEAD untracked files: git ls-files --others --exclude-standard而不是只看git diff十四、哪些变更文件不会进入Will reviewocr review --preview不只是列出 Git diff 中出现的文件还会判断这些文件是否真的会进入审查。Preview 输出里有两个重要区域Will review Excluded from review不是所有发生变更的文件都会进入Will review。OpenCodeReview 在拿到 diff 后还会经过文件过滤逻辑。常见被排除的原因包括1. 二进制文件 2. 被 .gitignore 或内置目录规则排除 3. 被 .opencodereview/rule.json 的 exclude 命中 4. 文件扩展名不在支持范围内 5. 位于默认排除路径例如 node_modules、vendor 等 6. 纯删除文件。所以ocr review --preview的价值不只是告诉我“哪些文件变了”还会告诉我哪些文件最终会被审查 哪些文件虽然变了但会被排除。这也为下一篇分析rule.json的exclude、path和规则匹配做了铺垫。十五、从源码角度简单理解 Preview 流程上一篇已经找到ocr review的入口在cmd/opencodereview/main.go并且会进入runReview(args[1:])在runReview中程序会先解析参数。当用户执行ocr review--preview时参数解析后可以简单理解为opts.preview true然后runReview会根据这个参数进入 preview 分支。整体流程可以先简单理解为用户执行 ocr review --preview ↓ main.go ↓ dispatch() ↓ runReview(args[1:]) ↓ parseReviewFlags(args) ↓ opts.preview true ↓ runPreview ↓ ag.Preview ↓ loadDiffs ↓ diff.Provider.GetDiff ↓ diff.ParseDiffText ↓ 生成 model.Diff ↓ whyExcluded / diffStatus ↓ outputPreviewText ↓ 终端显示 Preview 结果这里最重要的是model.Diff。它可以理解为 OpenCodeReview 内部对“单个文件变更”的结构化表示里面会保存OldPath / NewPath Diff 原始文本 NewFileContent 新文件内容 IsBinary / IsDeleted / IsNew / IsRenamed Insertions / Deletions所以ocr review --preview展示的文件路径、状态、7 -1不是凭空来的而是来自model.Diff中的结构化字段。目前只需要知道Preview 模式不会真正调用 LLM 它会加载 Git diff解析成 model.Diff应用文件过滤规则然后渲染预览结果。十六、理解几种常见文件状态在 Git diff 或 OCR Preview 中常见文件状态包括状态含义M/[M]Modified文件被修改A/[A]Added新增文件D/[D]Deleted删除文件R/[R]Renamed文件重命名B/[B]Binary二进制文件本次输出中出现的是[M]所以表示s01/src/user.js 是一个被修改的文件。如果后续新增一个文件例如src/order.js那么可能看到[A] src/order.js如果删除一个文件可能看到[D] src/old.js这些状态都来自 Git 对文件变更的判断。十七、理解三种 review 场景虽然本文主要使用的是当前工作区变更但ocr review还可以用于其他场景。1. 默认工作区模式直接执行ocr review或者ocr review--preview通常审查的是当前工作区中的变更。也就是还没有提交的修改。这是我目前练习时最常用的模式。2. Commit 模式也可以审查某一个 commitocr review--commitabc123它表示审查 abc123 这个提交相对于它父提交的代码差异。这种方式适合在某次提交后单独审查。3. From-To 模式还可以审查两个 Git 引用之间的差异ocr review--frommain--tofeature-branch它表示审查 main 到 feature-branch 之间的代码变化。这类模式更接近 Pull Request 或分支对比场景。十八、为什么 Git Diff 是 Agent Review 的第一步现在可以重新理解ocr review的流程。一开始以为它大概是把代码发给 LLM ↓ LLM 给出评论但现在通过 Git diff 观察发现它至少要先完成识别变更文件 统计新增删除行数 判断文件状态 过滤不需要审查的文件 确定本次审查范围这些都属于 LLM 之前的确定性工程处理。也就是说ocr review的第一步不是调用大模型而是先通过 Git diff 确定输入。然后后续才会进入规则匹配 文件读取 上下文检索 Agent 工具调用 LLM 审查 评论输出所以 Git diff 是整个代码审查流程的起点。十九、本篇使用的 PowerShell 命令记录为了方便复盘本文主要使用了下面这些命令。1. 进入练习项目cd D:\agent\open-code-review-main\ocr-practice-demo2. 查看 Git 状态git status--short3. 查看变更文件状态gitdiff--name-status4. 查看新增和删除行数gitdiff--numstat5. 查看 diff 统计gitdiff--stat6. 查看具体 diff 内容gitdiff7. 查看 OCR Previewocr review--preview二十、本篇总结通过这一篇对ocr review的输入有了更清晰的理解。本文最核心的结论是ocr review 的核心输入是 Git diff。Git diff 会告诉 Open Code Review哪些文件发生了变化 文件是新增、修改还是删除 新增了多少行 删除了多少行 具体变更内容是什么。本次示例中Git 检测到1 个文件被修改 新增 7 行 删除 1 行。所以ocr review --preview输出Preview: 1 file(s) changed | 7 -1 Will review (1): [M] s01用最小 Demo 跑通 AI 代码审查/src/user.js其中[M] 表示文件被修改 7 表示新增 7 行 -1 表示删除 1 行。而-1的来源是- deleteUser deleteUser,也就是说它不是删除了业务逻辑而是 Git 认为原来的deleteUser这一行被替换成了新的deleteUser,。通过这一篇已经能把下面几类输出对应起来git status --short git diff --name-status git diff --numstat git diff --stat ocr review --preview二十一、下一篇自定义规则 rule.json 解析第一篇中已经配置过.opencodereview/rule.json并且通过ocr rules check src/user.js验证了规则可以命中 JavaScript 文件。第三篇解决的是ocr review 的输入 Git diff 是怎么来的下一篇准备继续分析从 0 学习 Alibaba Open Code Review自定义规则 rule.json 解析下一篇主要解决这些问题1. 为什么 .opencodereview/rule.json 能影响审查结果 2. path: **/*.js 是如何匹配 src/user.js 的 3. rule 字段如何影响 Agent 的审查重点 4. merge_system_rule: true 是什么意思 5. exclude 如何影响审查范围 6. ocr rules check 的输出应该怎么看到这里学习路线就从ocr review 能做什么进入到ocr review 看哪些代码再继续进入ocr review 按什么规则审查代码
从 0 学习 Alibaba Open Code Review(三):Git Diff 解析流程
发布时间:2026/7/4 3:14:54
前言上一篇文章中从源码角度找到了ocr review的命令入口。当用户执行ocr review程序会从cmd/opencodereview/main.go进入命令分发逻辑然后进入runReview(args[1:])接着会调用parseReviewFlags(args)解析命令行参数。也就是说第二篇主要解决的是ocr review 是从哪里启动的这一篇继续往下学习一个更基础、也更关键的问题ocr review 为什么知道我改了哪个文件在第一篇中执行过ocr review--preview终端输出Preview: 1 file(s) changed | 7 -1 Will review (1): [M] s01/src/user.js当时只是知道OpenCodeReview 识别到了 s01/src/user.js 的变更。但是还不清楚[M] 是什么意思 7 -1 是怎么来的 为什么它知道要审查这个文件 ocr review --preview 和 git diff 有什么关系所以本文就围绕这些问题学习 Open Code Review 的核心输入Git Diff。一、本篇学习目标本文主要解决下面几个问题1. 什么是 Git diff 2. 为什么 ocr review 依赖 Git diff 3. git status、git diff 和 ocr review --preview 有什么关系 4. [M] 表示什么 5. 7 -1 是怎么统计出来的 6. 为什么 Git diff 中会出现 -1 7. ocr review --preview 做了什么这一篇关注Open Code Review 是如何识别本次代码变更的二、为什么先学习 Git Diffocr review和ocr scan不一样。ocr scan更偏向全量扫描目录或文件而ocr review的核心是审查本次代码变更。也就是说ocr review首先要知道这次改了哪些文件 每个文件新增了多少行 每个文件删除了多少行 哪些文件需要审查 哪些文件应该排除这些信息主要来自 Git。所以可以先简单理解为Git diff 是 ocr review 的输入。如果没有 Git diffocr review就不知道本次要审查哪些代码变更。这也是为什么 Open Code Review 适合用于本地未提交变更审查 commit 审查 分支差异审查 Pull Request 审查因为这些场景的本质都是比较两份代码之间的差异。三、准备一个代码变更为了方便观察 Git diff在练习项目中修改了s01/src/user.js本次新增了一个函数functionupdateUserEmail(db,userId,email){db.query(UPDATE users SET email email WHERE id userId);returntrue;}并且在module.exports中导出了它module.exports{getUserName,login,buildUserQuery,fetchUser,deleteUser,updateUserEmail};这个函数写得比较简单而且包含明显的问题1. SQL 字符串拼接 2. 没有参数化查询 3. 没有错误处理 4. 总是 return true。不过这一篇不分析代码审查结果只分析 Git diff 和 preview 输出。四、查看当前 Git 状态首先进入练习项目目录cd D:\agent\open-code-review-main\ocr-practice-demo然后执行git status--short输出结果中可以看到M s01/src/user.js这里的M表示文件被修改了。也就是说Git 已经检测到s01/src/user.js 发生了修改。注意这里的M是 Git 原生输出中的文件状态。后面ocr review --preview中看到的[M]也是类似含义表示Modified文件被修改。五、查看变更文件状态git diff --name-status接着执行gitdiff--name-status输出类似M s01/src/user.js这条命令只关心哪些文件变了 这些文件是什么状态其中M Modified修改文件 A Added新增文件 D Deleted删除文件 R Renamed重命名文件所以这次输出M s01/src/user.js表示s01/src/user.js 是一个被修改的文件。这和ocr review --preview中的[M] s01/src/user.js是对应的。六、查看新增和删除行数git diff --numstat继续执行gitdiff--numstat输出结果7 1 s01/src/user.js这三个部分分别表示7 新增行数 1 删除行数 文件路径所以这次变更可以理解为src/user.js 新增了 7 行删除了 1 行。这个输出可以帮助我们验证ocr review --preview中7 -1的含义7 insertions → 7 1 deletion → -1需要注意这里是用git diff --numstat辅助理解 Preview 输出并不表示 OpenCodeReview 源码中直接调用了git diff --numstat。从源码角度看OpenCodeReview 会先获取 unified diff 文本再解析 diff 内容统计每个文件的新增行和删除行。七、查看 diff 统计git diff --stat继续执行gitdiff--stat输出结果.../src/user.js | 8 - 1 file changed, 7 insertions(), 1 deletion(-)这条输出更适合人阅读。它说明1 个文件发生变化 新增了 7 行 删除了 1 行。其中7 insertions()表示新增 7 行。1 deletion(-)表示删除 1 行。这和前面的git diff --numstat、ocr review --preview是一致的。可以整理成下面的对应关系命令输出含义git diff --name-statusM s01/src/user.js文件被修改git diff --numstat7 1 s01/src/user.js新增 7 行删除 1 行git diff --stat1 file changed, 7 insertions, 1 deletion变更统计ocr review --preview[M] src/user.js 7 -1Open Code Review 预览审查范围八、查看具体 diff 内容接下来执行gitdiff可以看到具体代码差异diff --git a/s01用最小 Demo 跑通 AI 代码审查/src/user.js b/s01用最小 Demo 跑通 AI 代码审查/src/user.js index 1445e1f..f9f2188 100644 --- a/s01/src/user.js b/s01/src/user.js -33,10 33,16 function deleteUser(db, userId) { return true; } function updateUserEmail(db, userId, email) { db.query(UPDATE users SET email email WHERE id userId); return true; } module.exports { getUserName, login, buildUserQuery, fetchUser, - deleteUser deleteUser, updateUserEmail };这段 diff 是理解7 -1的关键。其中这一行叫做 hunk header -33,10 33,16 function deleteUser(db, userId) {可以简单理解为-33,10 表示旧文件从第 33 行开始共 10 行 33,16 表示新文件从第 33 行开始共 16 行。这类行号信息后面会非常重要因为 Agent 最终生成的code_comment需要定位到具体文件和具体代码行。九、理解 diff 中的和-在 Git diff 中 表示新增行 - 表示删除行例如下面这几行function updateUserEmail(db, userId, email) { db.query(UPDATE users SET email email WHERE id userId); return true; } 这些都是新增行。所以它们会被统计到7而这一行- deleteUser表示旧版本中原来是deleteUser后来变成了 deleteUser, updateUserEmail也就是deleteUser,updateUserEmail所以 Git 认为旧的 deleteUser 这一行被删除 新的 deleteUser, 这一行被新增 updateUserEmail 这一行也被新增。这就是为什么只是加了一个逗号却会出现-1十、执行ocr review --preview接下来执行 Open Code Review 的预览命令ocr review--preview输出结果[ocr] A new version (v1.7.0) is available. Run to update: npm i -g alibaba-group/open-code-review1.7.0 Preview: 1 file(s) changed | 7 -1 Will review (1): [M] s01/src/user.js真正重要的是Preview: 1 file(s) changed | 7 -1以及Will review (1): [M] s01/src/user.js这说明 Open Code Review 识别到了1 个文件发生变化 新增 7 行 删除 1 行 这个文件会被纳入审查 文件状态是 Modified。十一、把 Git 输出和 OCR Preview 对应起来现在可以把 Git 原生命令和 Open Code Review Preview 输出对应起来。1. 文件数量对应git diff --stat输出1 file changedocr review --preview输出Preview: 1 file(s) changed二者对应Git 检测到 1 个文件变化 ↓ OCR Preview 显示 1 file(s) changed2. 文件状态对应git diff --name-status输出M s01用最小 Demo 跑通 AI 代码审查/src/user.jsocr review --preview输出[M] s01/src/user.js二者对应Git 中的 M ↓ OCR Preview 中的 [M]含义都是Modified文件被修改。3. 新增删除行数对应git diff --numstat输出7 1 s01用最小 Demo 跑通 AI 代码审查/src/user.jsocr review --preview输出7 -1二者对应7 insertions ↓ 7 1 deletion ↓ -1所以ocr review --preview展示的7 -1本质上来自本次 Git diff 的新增和删除行数统计。十二、ocr review --preview的作用通过前面的对比可以发现ocr review --preview的作用是在不真正调用 LLM 的情况下 提前告诉我这次会审查哪些文件。它可以帮助我在正式执行审查前确认几个问题1. 当前是否有 Git 变更 2. 哪些文件会被审查 3. 哪些文件被排除 4. 每个文件的变更规模是多少 5. 文件状态是新增、修改还是删除。这一步非常重要。因为正式执行ocr review会调用 LLM可能产生 token 消耗和等待时间。所以在正式 review 前先执行ocr review--preview可以避免一些问题。例如不小心审查了无关文件 忘记忽略生成文件 把 JSON 结果文件也纳入了 review 当前其实没有代码变更 审查范围比预期大很多。因此使用习惯是先执行 ocr review --preview 确认范围没问题 再执行 ocr review十三、为什么git diff和 Preview 有时对不上本文示例中的修改是未暂存的 tracked 文件所以git diff、git diff --numstat和ocr review --preview的结果可以很好地对应起来。但在真实项目里有时你会发现git diff 看不到某些文件 ocr review --preview 却能看到。原因是 OpenCodeReview 的 workspace 模式不只是简单执行裸git diff。从源码逻辑看workspace 模式会处理两类变更1. tracked 文件变更通过 git diff HEAD 获取相对 HEAD 的变更 2. untracked 文件变更通过 git ls-files --others --exclude-standard 找到未跟踪文件并手动构造 diff。这意味着如果文件已经 git add普通 git diff 可能看不到因为它默认比较工作区和暂存区 如果文件是 untracked普通 git diff 也看不到因为它还没有进入 Git 跟踪 但 ocr review --preview 仍然可能把它们纳入审查范围。所以在对照 OCR Preview 时更接近的理解方式是tracked changes: git diff HEAD untracked files: git ls-files --others --exclude-standard而不是只看git diff十四、哪些变更文件不会进入Will reviewocr review --preview不只是列出 Git diff 中出现的文件还会判断这些文件是否真的会进入审查。Preview 输出里有两个重要区域Will review Excluded from review不是所有发生变更的文件都会进入Will review。OpenCodeReview 在拿到 diff 后还会经过文件过滤逻辑。常见被排除的原因包括1. 二进制文件 2. 被 .gitignore 或内置目录规则排除 3. 被 .opencodereview/rule.json 的 exclude 命中 4. 文件扩展名不在支持范围内 5. 位于默认排除路径例如 node_modules、vendor 等 6. 纯删除文件。所以ocr review --preview的价值不只是告诉我“哪些文件变了”还会告诉我哪些文件最终会被审查 哪些文件虽然变了但会被排除。这也为下一篇分析rule.json的exclude、path和规则匹配做了铺垫。十五、从源码角度简单理解 Preview 流程上一篇已经找到ocr review的入口在cmd/opencodereview/main.go并且会进入runReview(args[1:])在runReview中程序会先解析参数。当用户执行ocr review--preview时参数解析后可以简单理解为opts.preview true然后runReview会根据这个参数进入 preview 分支。整体流程可以先简单理解为用户执行 ocr review --preview ↓ main.go ↓ dispatch() ↓ runReview(args[1:]) ↓ parseReviewFlags(args) ↓ opts.preview true ↓ runPreview ↓ ag.Preview ↓ loadDiffs ↓ diff.Provider.GetDiff ↓ diff.ParseDiffText ↓ 生成 model.Diff ↓ whyExcluded / diffStatus ↓ outputPreviewText ↓ 终端显示 Preview 结果这里最重要的是model.Diff。它可以理解为 OpenCodeReview 内部对“单个文件变更”的结构化表示里面会保存OldPath / NewPath Diff 原始文本 NewFileContent 新文件内容 IsBinary / IsDeleted / IsNew / IsRenamed Insertions / Deletions所以ocr review --preview展示的文件路径、状态、7 -1不是凭空来的而是来自model.Diff中的结构化字段。目前只需要知道Preview 模式不会真正调用 LLM 它会加载 Git diff解析成 model.Diff应用文件过滤规则然后渲染预览结果。十六、理解几种常见文件状态在 Git diff 或 OCR Preview 中常见文件状态包括状态含义M/[M]Modified文件被修改A/[A]Added新增文件D/[D]Deleted删除文件R/[R]Renamed文件重命名B/[B]Binary二进制文件本次输出中出现的是[M]所以表示s01/src/user.js 是一个被修改的文件。如果后续新增一个文件例如src/order.js那么可能看到[A] src/order.js如果删除一个文件可能看到[D] src/old.js这些状态都来自 Git 对文件变更的判断。十七、理解三种 review 场景虽然本文主要使用的是当前工作区变更但ocr review还可以用于其他场景。1. 默认工作区模式直接执行ocr review或者ocr review--preview通常审查的是当前工作区中的变更。也就是还没有提交的修改。这是我目前练习时最常用的模式。2. Commit 模式也可以审查某一个 commitocr review--commitabc123它表示审查 abc123 这个提交相对于它父提交的代码差异。这种方式适合在某次提交后单独审查。3. From-To 模式还可以审查两个 Git 引用之间的差异ocr review--frommain--tofeature-branch它表示审查 main 到 feature-branch 之间的代码变化。这类模式更接近 Pull Request 或分支对比场景。十八、为什么 Git Diff 是 Agent Review 的第一步现在可以重新理解ocr review的流程。一开始以为它大概是把代码发给 LLM ↓ LLM 给出评论但现在通过 Git diff 观察发现它至少要先完成识别变更文件 统计新增删除行数 判断文件状态 过滤不需要审查的文件 确定本次审查范围这些都属于 LLM 之前的确定性工程处理。也就是说ocr review的第一步不是调用大模型而是先通过 Git diff 确定输入。然后后续才会进入规则匹配 文件读取 上下文检索 Agent 工具调用 LLM 审查 评论输出所以 Git diff 是整个代码审查流程的起点。十九、本篇使用的 PowerShell 命令记录为了方便复盘本文主要使用了下面这些命令。1. 进入练习项目cd D:\agent\open-code-review-main\ocr-practice-demo2. 查看 Git 状态git status--short3. 查看变更文件状态gitdiff--name-status4. 查看新增和删除行数gitdiff--numstat5. 查看 diff 统计gitdiff--stat6. 查看具体 diff 内容gitdiff7. 查看 OCR Previewocr review--preview二十、本篇总结通过这一篇对ocr review的输入有了更清晰的理解。本文最核心的结论是ocr review 的核心输入是 Git diff。Git diff 会告诉 Open Code Review哪些文件发生了变化 文件是新增、修改还是删除 新增了多少行 删除了多少行 具体变更内容是什么。本次示例中Git 检测到1 个文件被修改 新增 7 行 删除 1 行。所以ocr review --preview输出Preview: 1 file(s) changed | 7 -1 Will review (1): [M] s01用最小 Demo 跑通 AI 代码审查/src/user.js其中[M] 表示文件被修改 7 表示新增 7 行 -1 表示删除 1 行。而-1的来源是- deleteUser deleteUser,也就是说它不是删除了业务逻辑而是 Git 认为原来的deleteUser这一行被替换成了新的deleteUser,。通过这一篇已经能把下面几类输出对应起来git status --short git diff --name-status git diff --numstat git diff --stat ocr review --preview二十一、下一篇自定义规则 rule.json 解析第一篇中已经配置过.opencodereview/rule.json并且通过ocr rules check src/user.js验证了规则可以命中 JavaScript 文件。第三篇解决的是ocr review 的输入 Git diff 是怎么来的下一篇准备继续分析从 0 学习 Alibaba Open Code Review自定义规则 rule.json 解析下一篇主要解决这些问题1. 为什么 .opencodereview/rule.json 能影响审查结果 2. path: **/*.js 是如何匹配 src/user.js 的 3. rule 字段如何影响 Agent 的审查重点 4. merge_system_rule: true 是什么意思 5. exclude 如何影响审查范围 6. ocr rules check 的输出应该怎么看到这里学习路线就从ocr review 能做什么进入到ocr review 看哪些代码再继续进入ocr review 按什么规则审查代码