【免费下载链接】weave
Entity-level git merge driver. Resolves false conflicts git invents when independent agents edit the same file. ~95% reduction vs. line-based merge.
weave 是一款实体级(entity-level)Git 合并驱动,基于 tree-sitter 语言注册表对 38 种编程语言和格式做函数、类、键级别的语义合并,能消除 Git 按行合并时产生的大量"假冲突"。本文带你拆解 weave 的语言支持体系:注册表如何做到"零手工维护"、每种语言必须通过的五个覆盖测试,以及为什么 Vue 和 Haskell 被刻意排除在外。
一、为什么"支持语言"是 weave 的核心工程
Git 的合并以行为单位:两个分支只要往同一文件的不同函数里加代码,就可能因行区间重叠而报冲突。weave 的做法相反——先用 tree-sitter 把 base、ours、theirs 三个版本解析成语义实体(函数、类、JSON 键等),再在实体粒度上做三路合并。
这意味着"支持一种语言"不是加个配置项那么简单,它要求三件事同时成立:
- 有可工作的 tree-sitter 语法解析器;
- 解析出的实体模型足够细(按定义拆分,而不是整文件一块);
- 该模型下的合并行为经过验证:该干净的干净,该冲突的必须冲突。
下图演示了典型场景:两个分支各加一个函数,Git 报冲突,weave 干净合并。
二、tree-sitter 语言注册表:唯一的真相来源
很多工具用一张"手工维护的支持语言清单",清单和解析器能力迟早脱节。weave 的设计是派生而非罗列:
- 合并引擎持有一个静态的 parser registry(crates/weave-core/src/merge.rs),由 sem-core 的
create_default_registry构建,包含全部编译进来的 tree-sitter 语法。 weave setup写入.gitattributes的扩展名列表,直接调用supported_merge_extensions()(merge.rs)从注册表实时读取:注册表认识的所有扩展名,减去被拒绝的,就是 setup 会声明的。上游新增一个语法,setup 自动多认领对应扩展名,两者不可能漂移。- 反向也有守卫:parity 测试(crates/weave-core/tests/setup_extension_coverage.rs)断言"每一个注册扩展名要么被 setup 发射、要么被显式拒绝,绝不能悄悄漏掉",并额外检查 setup 不会发明引擎无法兑现的覆盖(如
.lock这类不可解析文件保持 Git 默认行合并)。
当前这 38 项覆盖:TypeScript、TSX、JavaScript、Python、Go、Rust、Java、C、C++、Ruby、C#、PHP、Swift、Kotlin、Scala、Dart、Elixir、Bash、Fish、Fortran、Perl、OCaml、Zig、Elm、Clojure、EDN、D、Lua、Nix、SQL、HCL/Terraform、LaTeX、XML、JSON、YAML、TOML、CSV、Markdown。
值得一提的细节:INI 文件(.ini/.cfg)没有 tree-sitter 语法,但也走了注册表通道(LINE_RULE_EXTENSIONS),采用 Git 行合并加"同一 section 内双方新增的键取并集"的规则——能力边界在哪,行为就精确到哪。
三、五场景覆盖测试:每种语言必须通过 5 道关卡
进入支持列表的"入场券"在 crates/weave-core/tests/language_coverage.rs。每种语言用三个可互换的定义(alpha/beta/gamma)组装出相同的五组合成三路合并,全部通过才允许列入:
| 场景 | 操作 | 期望结果 |
|---|---|---|
| 1. 不相交新增 | 双方各加一个不同定义 | 干净合并,两个新增都保留 |
| 2. 新增对修改 | ours 改写定义、theirs 新增定义 | 干净合并,两边编辑都不丢 |
| 3. 矛盾改写 | 双方把同一定义改成不同值 | 必须冲突,且冲突框携带双方声明 |
| 4. 单侧静止 | theirs 无变化 | 干净合并,结果与 ours 逐字节一致 |
| 5. 相同编辑两次 | 双方做了完全相同的修改 | 干净合并,编辑只出现一次 |
场景 1、2、4 验证"不丢东西";场景 3 防止引擎为求"全干净"而悄悄吞掉编辑;场景 5 验证幂等。测试文件的注释说得很直白:过不了全部五项的语言,不配进支持列表(language_coverage.rs)。
四、为何刻意放弃 Vue、Svelte、ERB 和 Haskell
这是本文标题的重点,也是 weave 最有纪律性的地方:这四类文件能被解析,但合并效果比 Git 还差,所以被显式拒绝(DECLINED_EXTENSIONS,见 merge.rs),交给 Git 的行合并处理。
原因都出在实体模型太粗(language_coverage.rs):
.vue/.svelte:整个<script>块是一个实体。于是脚本里任何位置的编辑都互相竞争——双方各加两个函数这种最常见的合并直接冲突,且冲突标记框会从函数签名和函数体中间切过。.erb:整个模板是一个实体,两个互不相干的<% def %>新增也会冲突,标记会把<% end %>与代码块分离。.hs(Haskell):解析器把类型签名当作实体,绑定行却算作间隔文本。不相交新增时两边会漂移:输出把beta :: String配上了alpha = "base_value",一个绑定被复制、另一个被框住——这是丢失工作成果,而不是冲突。
weave 的判断标准不是"能解析就算支持",而是"不能比 Git 更差"。这些文件走行合并是当下更优的答案。它们随时可能回来:一旦解析器获得真正的按定义实体模型,把 fixture 加回 sweep 测试,通过五项就能重新赢得支持列表中的一席之地。
这种"拒绝清单"本身也被测试看守:Svelte 的整个复合后缀家族(.svelte.js、.svelte.spec.ts等)都必须拒绝,注册表若新增遗漏的变体,parity 测试会直接让构建失败。
五、从注册表到工作流:一次 setup 如何生效
理解了三道防线(注册表 → sweep 测试 → parity 守卫),再看用户侧的落地就一目了然:
weave setup # 从注册表派生 .gitattributes,逐扩展名写入 merge=weavesetup 的扩展名映射逻辑在 crates/weave-cli/src/commands/setup.rs:注册表扩展名减去拒绝清单,加上 INI 行规则类,映射成*.ts、*.kt等 glob。weave setup --global可让所有仓库默认走 weave,--local只写.git/info/attributes不影响他人。
从 0.5.3 的 CHANGELOG 可以看到这套体系的威力:引擎早已能解析 Kotlin、Terraform、OCaml 等语言,只是 setup 从未来认领;改用注册表派生后,17 个扩展名一次性补齐,总数到达 38,且 Vue/Svelte/ERB/Haskell 被明确移出。
其他兜底规则也值得知道:超过 1MB 的文件、二进制文件、无解析器的类型自动回退到 Git 行合并(STRUCTURE_LIMIT_BYTES,见 merge.rs)——注册表声明的每一行承诺,引擎都有能力兑现。
六、安装与上手
brew install weave # 或源码构建(需要 Rust 工具链)源码构建需要两个二进制(CLI 与 Git 实际调用的 driver):
git clone https://gitcode.com/gh_mirrors/weave17/weave cd weave cargo install --path crates/weave-cli # weave 命令 cargo install --path crates/weave-driver # git 调用的合并驱动装好后在任意仓库执行weave setup,日常照常用git merge:真实冲突落地为带refused_by:说明的标记,随后用weave explain <file>查看每个冲突实体的详情、weave check校验你的手工解决、weave preview <branch>无副作用地预演合并结果。
总结
weave 对"38 种语言支持"的态度可以概括为三条工程纪律:
- 派生而非罗列——支持范围永远等于 tree-sitter 注册表的实时能力减去显式拒绝集,杜绝清单漂移;
- 测试即准入——五场景 sweep 是每种语言的硬门槛,"过不了就不列";
- 拒绝也是特性——Vue、Svelte、ERB、Haskell 因实体模型过粗被刻意排除,宁可交还给 Git 行合并,也不制造更差的冲突。
正是这种克制,让 weave 在 31 个手工场景基准上保持 31/31 的正确率——包括那两处"合并成功反而是错的"装饰器场景。
【免费下载链接】weave
Entity-level git merge driver. Resolves false conflicts git invents when independent agents edit the same file. ~95% reduction vs. line-based merge.
相关推荐
19GB实现95%性能保留:Qwen3-32B-AWQ如何开启大模型普惠时代
19GB实现95%性能保留:Qwen3 32B AWQ如何开启大模型普惠时代 导语 阿里巴巴通义千问团队推出的Qwen3 32B AWQ量化模型,通过4位AWQ
文档教程终极指南:如何为你的编程语言创建 Tree-sitter 语法解析器
终极指南:如何为你的编程语言创建 Tree sitter 语法解析器 Tree sitter 是一个革命性的增量解析系统,专为编程工具设计。这个强大的解析器生成
开发工具gRPC多语言支持:如何在10种编程语言中使用gRPC
gRPC多语言支持:如何在10种编程语言中使用gRPC gRPC是一个开源的远程过程调用框架,专为构建高性能分布式应用程序而设计。它提供强大的多语言支持,让开发
后端RPC框架微服务通信
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考