当 BitTorrent 创始人 Bram Cohen 在 GitHub 上发布名为「Manyana」的版本控制项目时,社区意识到这并非一次简单的技术试水。Cohen 花费大量篇幅论证了一个核心命题:CRDT(无冲突复制数据类型)是版本控制的「根本性健全基础」,这一观点直指 Git 等传统版本控制系统在复杂合并场景下的结构性缺陷。Manyana 作为 Cohen 对版本控制未来的系统性思考,其设计理念与工程实践值得深入剖析。
为什么版本控制需要 CRDT
传统版本控制系统在处理合并时依赖启发式算法和最近公共祖先( LCA)推演。Git 的三维合并算法虽然在大多数场景下表现良好,但面对复杂的交叉合并历史时,往往会产生难以理解的冲突,甚至在某些边界情况下出现静默丢失数据的问题。Cohen 在 Manyana 的设计文档中指出,这种「近似」策略在复杂的合并历史中会以痛苦的方式失效。
CRDT 为这一问题提供了原则性的解决方案。其核心属性 —— 交换律和结合律 —— 使得合并操作具有确定性:无论以何种顺序合并分支,最终结果都完全一致。这正是传统 VCS 试图通过复杂启发式近似但从未真正实现的能力。Manyana 的核心创新在于,它不仅实现了 CRDT 的技术特性,还解决了另一个关键难题:如何在「无冲突」的 CRDT 架构中呈现有意义的冲突信息给用户。
Weave 数据结构与状态表示
Manyana 采用「weave」(编织)作为核心数据结构。这是一个单一的线性结构,其中交错排列着文件中曾经出现过的每一行及其元数据。其状态大小与文件中曾经出现过的行数呈线性关系 —— 整个文件的历史保存在一个结构中,这个结构比最长版本大不了多少。这种设计在存储效率上具有显著优势,虽然在现代硬件条件下 Git 的存储浪费并非关键痛点,但这种紧凑性本身就是一个令人愉悦的特性。
每一行跟踪三个元数据字段:深度(编码插入的树结构,使算法知道哪些行相对于哪些其他行被插入)、锚点方向(记录一行是插入在其邻接行的上方还是下方,跨合并保留位置意图)以及代计数(一个整数,在每次添加 / 删除循环时递增,奇数表示存在,偶数表示已删除)。在合并时,较高的计数获胜,确保关于行状态的最知识被保留。
冲突展示的 UX 突破
CRDT 本质上是「无冲突」的 —— 每次合并都产生确定结果,但这并不意味着没有值得向用户展示的冲突。Manyana 的启发式规则是:当并发编辑「太接近」时 —— 即在文档结构中足够接近,以至于人类应该审查合并结果而不是让它静默自动合并 —— 则标记为冲突。具体来说,「接近」意味着立即相邻或仅以空行分隔。
Cohen 展示了一个具体示例:文件包含一个函数,一人删除了整个函数,另一人在函数中间添加了一行日志。传统 VCS 给出的是两个不透明的信息块,只能看出,一边是空的,另一边有代码,必须在脑海中重建实际发生了什么。Manyana 的输出则明确标注了每一边执行的操作:左侧执行了删除,右侧执行了插入。这种展示方式既更有信息量,也更诚实 —— 它不会将冲突强制塞进「我们的 vs 他们的」的二元框架。
线性复杂度与工程参数
Manyana 在工程实现上展现了令人印象深刻的特性。状态大小与文件中曾经出现过的行数呈线性关系,对两个状态执行合并是一次单独的线性遍历。这意味着无论仓库历史多长,合并操作的性能是可预测的。API 设计极为简洁,仅包含四个公共函数:initial_state 用于从行列表创建新状态,current_lines 用于从状态重建当前可见行,update_state 用于记录新版本(相当于提交),merge_states 用于合并两个分歧的状态并返回合并状态及带冲突标注的行。
在代计数(generation counting)策略上,Cohen 做出了一个务实的技术决策。当删除一个先前添加的行时,存在解释问题:这是前瞻性删除还是本地撤销?要想实现不依赖检查特定合并 ID 的结构性合并,代计数几乎是必然选择。另一种试图将删除完全解释为本地撤销的方法会导致极其复杂且难以推理的 case,而代计数则简单直接。
樱桃采摘问题与去中心化工作流
Cohen 还深入分析了 CRDT 系统中樱桃采摘(cherry-picking)的三种方法,其中两个是陷阱。压缩补丁方式可能导致真正奇怪的行为 —— 在看起来相同的代码之间合并会产生重复行。精确回放补丁的方式可行但脆弱 —— 需要完全正确的 diff 序列,任何偏差都会破坏等价性。正确的方法是历史范围选择 —— 选择状态中你想要樱桃采摘的历史范围并直接应用该切片。Manyana 的状态格式支持这种方式 —— 每行携带足够的元数据可以被提取和移植。
这种设计的核心理念是:universal permanent ordering(通用永久排序)是强需求。最终一致性意味着当多个分支合并在一起时,无论以何种顺序合并,结果都完全相同。这正是使去中心化工作流真正可行的属性。Cohen 详细论证了为什么没有通用排序会导致灾难性的结果 —— 两个解决相同冲突的人会独立产生不同的结果,导致冲突在每次合并时都重新生成。
与 Git 的生态位对比
Manyana 并非要替代 Git,而是面向特定的协作场景。其 high-level API 遵循熟悉的 git 流程(提交和合并),这降低了学习门槛。在去中心化工作流中,当没有规范的分支顺序时,CRDT 的数学特性确保了协作的可靠性。对于需要长期存档的项目、对抗审查的环境、或需要跨组织信任共建的基础设施代码,Manyana 提供了传统 VCS 难以企及的保证。
从 BitTorrent 的群体协作哲学,到 Chia 的空间时间证明,再到 Manyana 的 CRDT 版本控制,Cohen 一直在回答同一个根本问题:如何让分布式系统在不依赖中心权威的前提下可靠运行。Manyana 的诞生标志着他将这一理念延伸到了代码协作领域,为版本控制的未来提供了一个极具思考深度和技术创新性的方向。
资料来源
- Bram Cohen GitHub 仓库:bramcohen/manyana(Manyana: A Vision For The Future Of Version Control)
- Manyana 项目技术文档与实现代码