为什么 git diff 看不懂你的代码变更

0 阅读2分钟

你重命名了一个函数,git diff 给你显示 200 行红绿。你移动了一个方法到另一个文件,git diff 说你删了一段代码又加了一段新的。你只改了一个 if 条件,但 diff 里全是缩进变化。

这不是 diff 的 bug。这是因为 git diff 按行比较,而开发者按函数、类、方法思考。

行级 diff 的问题

git diff 把代码当纯文本。它不知道什么是函数,什么是类。所以:

  • 重命名一个变量,diff 里出现几十行变更
  • 调整了格式或缩进,diff 全是噪音
  • 两个函数交换了位置,diff 认为你重写了整段代码

Code review 的时候,你花大量时间过滤噪音,找到真正有意义的变更。PR 越大,噪音越多。

实体级 diff

sem 用 tree-sitter 把代码解析成 AST,提取出函数、类、方法这些实体,然后在实体级别做 diff。

一个函数被移动了?sem 告诉你它移动了,不会显示一堆删除和新增。

一个方法的签名变了?sem 只显示签名的变更,不会被周围的缩进变化干扰。

纯格式调整?sem 直接跳过。

实际效果

在一个真实的重构 PR 里(1200 行变更),git diff 显示了 47 个文件的变化。sem 把它缩减到 12 个实际被修改的实体。其余都是移动、重命名、格式调整。

Review 时间从 45 分钟降到 10 分钟。不是因为跳过了什么,而是因为噪音没了。

不只是 diff

当你有了实体级的理解,很多事情就变得可能:

  • 影响分析:改了这个函数,哪些下游函数会受影响?sem 构建跨文件的依赖图,可以直接回答
  • 语义 blame:这个函数最后一次被实质性修改是什么时候?不是最后一次格式调整,是真正改了逻辑的那次
  • 精准 code review:100 个变更实体里,哪 10 个风险最高?先 review 那 10 个

开始使用

brew install ataraxy-labs/sem-cli

语义 diff: sem diff HEAD~1

影响分析: sem impact src/auth.rs::verify_token

依赖图: sem graph src/main.rs

支持 30+ 种语言,包括 Rust、Python、TypeScript、Go、Java、C++、Swift、Kotlin、Ruby、C# 等。

GitHub: github.com/ataraxy-labs/sem