在传统版本控制系统中,如 Git,每一次提交都会创建一个快照,导致工作区与历史分离,用户需显式 commit 来保存状态。这种 “提交导向” 的范式在 AI 代理频繁修改代码、配置文件等场景下容易丢失中间状态。Unfudged 等工具通过文件系统事件监控实现连续记录,但仍停留在文件层面,缺乏真正的对象级分支与合并能力。本文聚焦单一技术点:使用持久化对象图(persistent object graphs)构建 “无提交” 版本控制系统,实现工作状态即历史状态的无缝导航与协作。
持久化对象图的核心原理
持久化对象图是一种纯函数式数据结构,每一次修改不就地变异原有对象,而是创建新版本的对象图,与旧版本通过结构共享(structural sharing)高效共存。每个对象节点包含内容哈希、字段值及引用指针,根节点代表整个图的版本标识。
例如,在 Rust 中,可使用 im 库或自定义 hash consing 实现:
- 对象 ID:BLAKE3 哈希(32 字节,防碰撞)。
- 版本根:指向根对象的哈希。
- 修改时:递归复制变更路径,仅新分配受影响节点(路径复制,amortized O (log N))。
这种设计避免了 “fudging”(临时序列化黑客),直接在内存 / 存储中操作图结构,支持任意时间点查询。
证据显示,这种方法在知识图谱版本控制中已验证有效:ConVer-G 等系统使用类似并发版本化图存储,实现多用户协作无锁访问。[1]
无提交工作流程:工作区即版本
传统 Git 有 staging area 与 commit 间隙;无提交 VC 将工作区视为 “活版本”(live version),每改动自动推入版本图。
实现参数:
- 监控 debounce:3 秒智能去抖(如 Unfudged),融合连续编辑为单版本,CPU 占用 <1%。
- 变更捕获:内存中对象引用追踪(RC/GC hooks)或代理(proxy objects)拦截 setField 操作。
- 自动版本化:每 debounce 周期,计算新根哈希,追加到线性历史链(或 DAG)。
示例伪代码(Go):
type Obj struct {
Hash [32]byte
Fields map[string]any
Refs []HashRef
}
func Update(root Hash, path []string, newVal any) Hash {
// 路径复制:仅更新叶节点
newObj := copyPath(root, path)
newObj.Fields[path[len(path)-1]] = newVal
return hashObj(newObj)
}
工作区始终指向最新根哈希,git status 等价 current_root := workspace.Root()。
分支与合并:版本图而非快照链
无需显式 commit,快照隐含在对象图中。分支即新根从父根衍生:
- 分支:
branch := Update(parent_root, path, val),新根引用共享父图。 - 历史导航:从根回溯父指针,O (1) 访问任意祖先。
- 合并:三路合并(ancestor, left, right),递归 diff 图节点:
- 相同哈希:共享,无冲突。
- 字段 diff:应用自定义 resolver(如 last-write-win 或 CRDT)。
落地清单:
- 存储后端:SQLite + content-addressed blobs(ACID 事务,每版本一事务)。
- 表:
objects(hash PRIMARY KEY, data BLOB)、versions(root_hash, parent_hash, ts, author)。 - 保留策略:24h 全版本、7 天小时级、30 天日级(自动 prune)。
- 表:
- 并发控制:乐观锁(版本哈希比较),冲突时重试或提示。
- 协作参数:
- P2P 同步:Gossip 根哈希 + delta patches(仅变更路径序列)。
- 冲突阈值:>10% 图变更时要求手动 merge。
- 性能阈值:
指标 阈值 监控点 CPU <1% 采样 debounce 周期 RAM <100MB / 项目 对象池复用 存储增长 <1MB / 小时 去重率 >90% Merge 时间 <5s (10k 节点) 图 diff 深度优先
回滚策略:restore(root_hash) 原子切换工作根,支持 dry-run 预览 diff。
优势与风险限界
相较文件级 Unfudged(仅线性回放),对象图支持语义合并:如两个分支同时改 User#123 的 email,自动检测并提示,而非文件覆盖。
风险:
- 循环引用:显式 ref 计数 + cycle detection。
- 大图膨胀:强制共享 + 定期 compact(rewrite DAG)。
在 AI 协作场景:代理修改对象图,人类 log --since 30m 查看 bursts,restore --at burst_start 回退。
此方案参数化强,可嵌入 IDE(如 VSCode extension)或 LangChain agents,支持多模型无缝切换上下文。
资料来源: [1] https://unfudged.io - Unfudged 文件记录器实现参考。 [2] https://news.ycombinator.com/item?id=36952796 - Jujutsu commitless 讨论,启发工作区即 commit 理念。
(正文字数:1028)