sem:1480⭐的语义版本控制CLI,让代码diff进入实体级别

传统Git diff基于文本行,当代码被格式化或变量重命名时,diff会变得嘈杂且难以阅读。sem 是一个基于tree-sitter的语义版本控制工具,它将diff粒度从”行”提升到”代码实体”级别。

核心特性

实体级Diff

不同于普通diff显示”第X行被修改”,sem能理解代码结构,显示”函数calculateTotal被修改”、“结构体User添加了字段email”。

# 查看语义diff
sem diff HEAD~1

# 输出示例:
# Modified: function calculateTotal in src/cart.js
#   - return price * quantity
#   + return price * quantity * (1 - discount)

语义Blame

追踪某个函数或变量的历史修改,而不是某行代码。

# 查看函数的修改历史
sem blame src/cart.js calculateTotal

依赖影响分析

修改一个函数时,sem能分析出哪些其他函数依赖于它,帮助评估变更影响范围。

# 分析变更影响
sem impact src/cart.js calculateTotal

可视化依赖图

生成代码实体间的依赖关系图,理解项目架构。

# 生成依赖图
sem graph --output deps.dot

技术实现

sem的核心是tree-sitter语法解析器,目前已支持21种语言:

  • 系统级: C, C++, Rust, Go
  • Web: JavaScript, TypeScript, HTML, CSS
  • JVM: Java, Kotlin, Scala
  • 其他: Python, Ruby, PHP, C#, Swift, OCaml, Haskell, Lua, Elm

解析代码后,sem提取语义实体(函数、类、变量等),构建实体关系图,所有的diff、blame、impact分析都基于此图结构进行。

安装

# 从源码编译
git clone https://github.com/Ataraxy-Labs/sem.git
cd sem
cargo install --path .

# 或使用预编译二进制文件(未来计划)

使用场景

代码审查

在PR review时,sem能清晰展示哪些逻辑被修改,过滤掉格式化变动:

sem diff main...feature-branch

重构辅助

重命名变量或提取函数时,确认所有相关地方都已更新:

sem blame src/utils.js helperFunction

架构分析

生成模块依赖图,发现循环依赖或过度耦合:

sem graph --module-level --output architecture.dot
dot -Tpng architecture.dot -o architecture.png

项目信息

属性详情
仓库https://github.com/Ataraxy-Labs/sem
语言Rust
Stars1,480
Forks44
许可证MIT
活跃度持续更新(日增约50⭐)

与Git的关系

sem不替代Git,而是作为Git的增强工具:

  • sem读取Git历史进行分析
  • 可与现有Git工作流无缝集成
  • 支持在Git hooks中调用sem进行代码分析
# 在pre-commit hook中使用
sem diff --staged --check-impact

总结

对于大型代码库或频繁重构的项目,sem提供了传统版本控制无法提供的语义层洞察。虽然项目相对年轻,但基于tree-sitter的稳健解析能力和Rust的高性能实现,使其成为开发者工具箱中有价值的补充。