news 2026/7/4 3:14:45

从 0 学习 Alibaba Open Code Review(三):Git Diff 解析流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从 0 学习 Alibaba Open Code Review(三):Git Diff 解析流程

前言

上一篇文章中,从源码角度找到了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 Diff

ocr reviewocr scan不一样。

ocr scan更偏向全量扫描目录或文件,而ocr review的核心是审查本次代码变更。

也就是说,ocr review首先要知道:

这次改了哪些文件? 每个文件新增了多少行? 每个文件删除了多少行? 哪些文件需要审查? 哪些文件应该排除?

这些信息主要来自 Git。

所以可以先简单理解为:

Git diff 是 ocr review 的输入。

如果没有 Git diff,ocr 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 --numstatocr 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-review@1.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 changed

ocr review --preview输出:

Preview: 1 file(s) changed

二者对应:

Git 检测到 1 个文件变化 ↓ OCR Preview 显示 1 file(s) changed

2. 文件状态对应

git diff --name-status输出:

M s01:用最小 Demo 跑通 AI 代码审查/src/user.js

ocr review --preview输出:

[M] s01/src/user.js

二者对应:

Git 中的 M ↓ OCR Preview 中的 [M]

含义都是:

Modified,文件被修改。

3. 新增删除行数对应

git diff --numstat输出:

7 1 s01:用最小 Demo 跑通 AI 代码审查/src/user.js

ocr 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 diffgit diff --numstatocr 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 review

ocr 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.jsonexcludepath和规则匹配做了铺垫。


十五、从源码角度简单理解 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 模式

也可以审查某一个 commit:

ocr 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-demo

2. 查看 Git 状态

git status--short

3. 查看变更文件状态

gitdiff--name-status

4. 查看新增和删除行数

gitdiff--numstat

5. 查看 diff 统计

gitdiff--stat

6. 查看具体 diff 内容

gitdiff

7. 查看 OCR Preview

ocr 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 按什么规则审查代码
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/4 3:14:20

第六篇:《内存分析工具:vmstat、smem、pmap、Valgrind》

理解了内存管理的原理之后,需要用工具把理论“可视化”。内存分析工具链可以分为三个层次:系统级(vmstat,看整体趋势)、进程级(smem、pmap,看具体进程的内存分布)和代码级&#xff0…

作者头像 李华
网站建设 2026/7/4 3:14:01

个人AI聊天机器人真的必要吗?三重过滤网评估技术适配度

1. 这不是又一个“AI聊天机器人教程”,而是一次对技术存在意义的诚实复盘“Rethinking the Necessity of Personal AI Chatbots in Modern Society”——这个标题里没有一行代码,不提任何模型参数,也没列一个部署步骤。它问的是一个被我们集体…

作者头像 李华
网站建设 2026/7/4 3:12:29

深入AI生产实践下,关于AI产品边界的深刻认识

一、局限性任何模型都永远存在三种局限性,即知识边界、推理边界、行为边界,只是对于不同模型有不同程度的体现。 1、知识边界:由于模型在特定任务下缺少相应的知识,而使用其泛化的理解力以实现目的,出现不稳定及不精准…

作者头像 李华
网站建设 2026/7/4 3:08:47

Direct3D Draw函数 异步调用原理解析

我们知道,实际渲染的过程大部分是在GPU上完成的,CPU只负责发号施令。实际上,数据准备完成后,当你的程序调用了Draw函数后,CPU才会真正的将数据和命令提交到GPU上进行渲染。从命令提交到渲染完成通常需要数十毫秒的时间…

作者头像 李华