首页
/
行业洞察
/
正文
INDUSTRY INSIGHT · 深度
Jujutsu 项目路线图深度解读:8 大技术方向与源码级现状
📅 2026/9/11 13:48:22
✍️ 爱科研究院
👁 阅读 3,247
Jujutsu 项目路线图深度解读8 大技术方向与源码级现状【免费下载链接】jjA Git-compatible VCS that is both simple and powerful项目地址: https://gitcode.com/GitHub_Trending/jj/jj本文以 Jujutsujj官方路线图文档 web/docs/src/content/docs/roadmap.md 为主体逐一剖析项目规划中的 8 个相互独立的技术目标文件复制/重命名追踪、Forge 集成、Git 子模块支持、面向 UI 的 Rust API 重构、RPC API、开源云端仓库服务端与守护进程、虚拟文件系统VFS与大文件支持。文章不仅完整保留路线图原文的目标描述还结合jj当前仓库中的设计文档、核心源码与测试用例给出每项规划的动机、已落地的实现证据与仍待解决的设计问题帮助读者准确判断 Jujutsu 的能力边界与发展方向。路线图总览一份没有时间表的愿望清单Jujutsu 官方路线图开宗明义它记录的是项目一些希望达成的目标且这些目标大多相互独立可以单独推进。文档同时特别说明绝大多数贡献者是在业余时间参与 Jujutsu 开发因此无法为任何目标附加预计完成日期。这一点对读者非常重要路线图中的每一项都代表项目希望做什么而非项目已经做了什么。要判断某项功能的真实落地程度必须回到仓库源码中去验证——这正是本文在每一节中都会做的事。路线图列出的 8 个目标分别是文件复制copy与重命名rename追踪Forge代码托管平台集成Git 子模块submodule支持面向 UI 的更好 Rust APIRPC API开源云端仓库服务端与守护进程虚拟文件系统VFS更好的大文件支持下文按路线图原文顺序逐一展开。1. 支持文件复制与重命名追踪目标与动机路线图提出Jujutsu 希望以把决策权交给 commit backend提交后端的方式支持复制追踪——即由后端决定是记录复制还是检测复制。这样做的好处是双重的兼容现有 Git 仓库Git 本身不记录复制/重命名而是在比较两个树时即时检测on the fly适配超大仓库在非常大的仓库中即时检测的开销可能高到不可接受此时一个能显式记录并重新提供复制信息的后端就更有优势。该项工作的完整设计思路记录在 docs/design/copy-tracking.md 中这也是路线图所链接的设计文档。设计要点把复制历史做成对象设计文档给出的核心思路是Jujutsu 采用与 Git 类似的基于快照snapshot的模型因此复制信息也必须融入快照模型中。具体方案是更新 tree 对象使其携带文件过去的名字。例如foo在某次提交中被重命名为bar之后又被重命名为baz那么baz的记录中就会包含它曾叫过bar和foo。为了支持多文件合并为一个文件的场景例如合并提交中两侧把不同源文件复制/重命名到同一个目标文件文件过去名字的列表实际是一个DAG有向无环图。为了避免在树条目中存储全部历史路径设计将复制历史单独写成对象树条目通过 ID 引用它——这与 commit ID 引用提交 DAG 节点的方式类似。设计文档给出了数据结构草案对应lib中的实现见下文// Current TreeValue::File variant: File { id: FileId, executable: bool }, // New TreeValue::File variant: File { id: FileId, executable: bool, copy_id: CopyId }, // A CopyId is a hash of this struct: struct CopyHistory { path: RepoPath, parents: VecCopyId }设计文档还讨论了两个值得注意的取舍是否给复制历史节点加盐salt如果只用文件名作为 ID 输入会得到确定性的树 ID如果加入盐则可以表达文件被彻底重写即使没有发生复制也得到新的 copy ID。设计者认为这在逻辑上说得通但当时不确定实际价值有多大符号链接与目录的追踪符号链接的历史对 blame 意义不大但可用于检测目录重命名当目录中所有文件和符号链接都被重命名时目录本身的复制追踪则因复杂度被暂缓。仓库中的实现证据从源码看这一目标在当前仓库中已有相当实质性的落地lib/src/backend.rs 定义了CopyId类型并有CopyId::placeholder()占位实现lib/src/backend.rs 定义了CopyRecord、CopyHistory含current_path、parents、salt字段与RelatedCopylib/src/backend.rs 中TreeValue::File变体已实际包含copy_id字段同时TreeValue还新增了GitSubmodule(CommitId)变体lib/src/copies.rs 实现了CopiesTreeDiffStream为 diff 流添加复制/重命名信息并区分CopyOperation::Copy与CopyOperation::Rename判断依据是源路径在目标树中是否仍存在lib/src/copies.rs 实现了CopyGraphIndexMapCopyId, CopyHistory、祖先/后代收集与is_ancestor判定lib/src/copies.rs 实现了CopyHistoryDiffStream即考虑复制历史的 diff 流并明确说明优先使用MergedTree::diff_stream_with_copy_history()见 lib/src/merged_tree.rsbackend trait 中新增了get_related_copies()与get_copy_records()两个查询方法lib/src/backend.rs这正是设计文档中让云后端用数据库索引加速复制查询的抽象接口。有意思的是各后端的支持程度并不一致Simple 后端lib/src/simple_backend.rs与Secret 后端lib/src/secret_backend.rs的get_related_copies目前都是空实现Git 后端lib/src/git_backend.rs的write_copy与get_related_copies明确返回BackendError::Unsupported错误信息为The Git backend doesnt support tracked copies yet——这与路线图Git 不记录复制、只做即时检测的描述完全吻合在 Git 后端上复制/重命名仍走检测路线。此外CLI 侧还有一个调试命令jj debug copy-detection用于打印某个修订相对其父提交检测到的文件复制信息cli/src/commands/debug/copy_detection.rs可以看作是复制检测能力的验证工具。对应的测试在 cli/tests/test_copy_detection.rs 中。设计文档中的复杂场景示例设计文档用大量命令历史示例验证了数据模型的表达能力这里选取两个最能说明问题的场景场景一发散复制与重命名divergent copy and renameM rename foo-baz, create bar || || L copy foo-bar, create baz ||/ K add foo从L到M的 diff 中foo、bar、baz的 copy 图互相关联。算法最终呈现四条记录baz被删除、bar被创建、foo被重命名为baz、bar被合并进baz——这需要最短路径匹配与已被占用目标不重复使用的约束。场景二收敛重命名convergent renames$ jj log C rename bar-baz || || B rename foo-baz ||/ A add foo, add bar $ jj new B C合并提交中baz的 copy 图应同时继承自foo与bar形成 copy 图中的 merge其树结构可表示为5:baz-{3:baz-1:foo, 4:baz-2:bar}。这正是复制历史是 DAG 而非链表的直接原因。设计文档还讨论了大量开放决策是否把变更跨复制传播最终结论是由jj resolve询问用户是否传播而非像 Mercurial 那样自动传播、Git 表示方式是否在 Git 对象之外额外存储重命名、克隆后是否后台做复制索引等。作为参照文档引用了实测数据git log --summary --find-copies-harder在 git.git 仓库约需 165 秒在 Nixpkgs 仓库约需 13 小时——这正是超大仓库中即时检测不可行的论据。2. Forge 集成目标与动机路线图希望让用户更方便地与各种流行的代码托管平台Forge如 GitHub、GitLab协作方式是提供类似jj github submit与jj gitlab submit的命令。对于流行的 Forge这些支持可能默认编译进标准jj二进制。仓库中的现状Gerrit 集成的参照当前仓库中已经存在一条完整的 Forge 集成实现——Gerrit。jj gerrit upload命令cli/src/commands/gerrit/upload.rs已经具备相当完整的上传流程将一组修订上传到 Gerrit 进行代码评审每个修订及所有可变祖先会创建一个独立的 change若某修订已存在对应 change含相同Change-Id则更新已有 change 的内容没有Change-Idtrailer 的提交会基于 Jujutsu change ID 生成一个但该 trailer 只添加到被上传的提交上因此上传后的 commit ID 可能与本地不同可能引发 divergence文档建议通过jj rebase --skip-emptied ...解决也可以在配置中通过[templates] commit_trailers使用format_gerrit_change_id_trailer(self)在本地自动添加Change-Id完整配置示例见 cli/src/commands/gerrit/upload.rs。从jj gerrit upload的成熟度可以推断GitHub/GitLab 的submit类命令在架构上并非无从下手它们大概率会复用同样的上传修订集 → 管理远端 change模式只是尚未列入实现计划。与之配套的测试位于 cli/tests/test_gerrit_upload.rs文档可参考 docs/gerrit.md。3. 子模块Submodule支持目标与动机路线图指出Git 子模块在大型 Git 仓库中使用得足够频繁因此 Jujutsu 大概率需要支持它们但UX用户体验方面仍存在大问题。这一目标的完整设计文档是 docs/design/git-submodules.md以及存储方案的讨论 docs/design/git-submodule-storage.md。该文档明确这是一份理想化的、描述 jj 未来将如何支持子模块的文档且仍在持续完善中。设计文档要点设计文档首先回顾了 Git 子模块的机制子模块是嵌入超级项目superproject的完整仓库拥有自己的 index、对象库与引用库超级项目提交中通过两个地方记录子模块信息树中的gitlink条目其值是被引用的子模块提交 ID顶层.gitmodules文件Git config 语法核心字段为submodule.name.path与submodule.name.url。工作区中Git 通过.git条目识别子模块其现代推荐形式是 absorbed form.git文件指向superproject-git-directory/modules/submodule-name。设计文档给出了分阶段路线作为指南而非严格顺序Phase 1只读子模块——支持全新克隆子模块、抓取新的子模块提交、查看子模块历史与分支、在工作区填充子模块内容、将超级项目 gitlink 更新/解决到已有子模块提交Phase 2快照新变更——允许把工作区新内容记录为子模块提交、修改子模块分支、推送到子模块远端Phase 3合并/变基/冲突——以内容感知方式区别于 Git 只比较 gitlink 提交 ID合并/变基超级项目提交并让冲突解决变得合理Phase ?理想世界——重写子模块提交时正确更新后代与超级项目 gitlink、子模块冲突自动解析到正确提交、嵌套子模块同样易用、操作日志记录子模块变更等。值得注意的非目标不支持非 Git 的子模块如原生 jj 子模块或其他 VCS、不支持非 Git 后端如 Google 内部后端、也不改变 Git 本身对子模块的实现。仓库中的现状从源码看子模块支持处于早期但方向明确的阶段lib/src/backend.rs 中TreeValue已包含GitSubmodule(CommitId)变体说明数据模型层面已经预留了子模块的位置lib/src/default_submodule_store.rs 与 lib/src/submodule_store.rs 中已有SubmoduleStoretrait 的雏形当前仅有name()方法配置层面存在git.submodule-...相关选项测试见 lib/tests/test_git.rs。这与设计文档Phase 1 起步的状态相符存储与只读管线正在搭建而快照、合并等更高阶段仍是开放的 UX 设计问题。4. 更好的 Rust API面向 UI 工具目标与动机路线图指出像gg这样的 UI 工具目前不得不从jj-cli复制相当多的逻辑。Jujutsu 需要把这些代码从 CLI 中解耦出来例如返回状态对象而非打印消息并移入jj-lib。这是一个架构层面的重构目标jj-lib应当成为可复用的库而 CLI 只是它的一个消费者。这与第 5 节的 RPC API 目标互为表里——前者解决Rust 内嵌复用后者解决跨语言/跨构建复用。仓库中的现状从仓库结构看jj-lib已经是一个非常完整的库包含事务、操作、修订集、树合并、工作副本等大量核心逻辑见 lib/src/lib.rs 及其下属模块。不过面向 UI 的状态对象化改造仍在进行中CLI 层的命令输出仍大量直接使用Ui的 stdout/stderr例如前文 cli/src/commands/gerrit/upload.rs 与 cli/src/commands/debug/copy_detection.rs 中的writeln!(ui.stdout(), ...)模式。由此可以推断将命令结果抽象为可编程状态对象、并下沉到jj-lib是一项尚未完成的重构工作。5. RPC API目标与动机路线图阐述了两个使用 Rust API 的问题后端耦合用 Rust API 编写的工具只能与它们编译时链接的后端一起工作。例如常规gg构建无法处理 Google 仓库因为它没有加载这些仓库所需的后端跨语言壁垒VS Code 这类非 Rust 编写的工具很难直接使用 Rust API。因此 Jujutsu 希望提供一种 RPC API工具通过运行类似jj api的命令获得一个地址来通信。RPC API 的抽象层级大概率高于 Rust API。路线图还暗示RPC API 的守护进程可能与第 6 节的云端仓库守护进程是同一个进程——这两项规划在架构上是耦合的。仓库中的现状从源码搜索来看当前仓库中尚不存在jj api命令在 cli/src/commands 目录下没有对应的 api 模块。这属于路线图中典型的已立项、未动工目标。不过其依赖基础操作日志、仓库加载、对象存储的抽象层在jj-lib中均已具备因此一旦启动主要是协议设计与 CLI 暴露层的工作。6. 开源云端仓库服务端与守护进程目标与动机这一节首次透露了 Google 内部的 Jujutsu 架构一个由数据库支撑的内部 Jujutsu 服务器把提交和仓库操作日志存储在云端即数据库中而工作副本仍保存在本地。为了降低延迟Google 内部还有一个本地守护进程负责缓存读写**预取prefetch**客户端接下来可能请求的对象通过乐观地应答写请求来降低写入延迟因此守护进程必须知道服务器的哈希方案才能返回正确的 ID。路线图表示项目而非 Google 本身希望为所有用户提供类似的体验因此计划创建类似的服务器与守护进程守护进程可能与 RPC API 是同一个进程。仓库中的现状与推论当前开源仓库中没有云端服务器的实现但存在若干与之配套的设计线索copy-tracking设计文档中专门有一节 Representation in cloud repo (e.g. Google)见 docs/design/copy-tracking.md讨论在同步到更新主线分支时如何利用 copy ID 判断文件是否被重命名以及为何需要后端提供按 copy ID 拉取完整复制图的方法该节还提醒了一个安全细节服务器可能只想为公共/不可变提交构建索引否则用户可以通过大量创建复制来投毒索引使未来查询变慢backend trait 中的get_related_copies/get_copy_records抽象lib/src/backend.rs正是为用数据库索引实现这些查询的云后端预留的接口。这些证据支持一个判断云端仓库方向的后端接口抽象已经就位但开源实现尚未开始。7. 虚拟文件系统VFS目标与动机对于非常大的项目和/或大文件更新工作副本可能非常昂贵。VFS 的构想是更新工作副本到另一个提交时只需告诉 VFS 以该提交为基准目标提交中的大文件直到用户通过文件系统真正请求时才下载VFS 通过跟踪相对基准提交的所有变更让快照工作副本变得廉价。路线图还特别指出VFS 对jj run也非常有益——因为可以廉价地为命令创建临时工作副本。仓库中的现状jj run已落地VFS 尚未jj run命令本身已经完整实现详见 cli/src/commands/run.rs其设计文档 docs/design/run.md 在Context and Scope一节中明确写道目前没有任何开源 Jujutsu 后端Git、Simple拥有支持它的花哨虚拟文件系统所以我们无法应用这项优化。我们只能将命令运行在常规本地磁盘工作副本中……一旦我们有了基于虚拟文件系统的工作副本实现我们就能做到同样的事。从jj run的实现细节可以清晰看到临时工作副本机制的现实形态每个并行任务使用.jj/run/default/N/下的一个固定工作副本槽位WorkspacePool见 cli/src/commands/run.rs槽位通过.jj/run/default/N.lock锁文件做进程间互斥工作副本在多次jj run调用之间持久复用以便复用构建产物如 cargo 的target/目录--clean参数可强制清空命令运行后会快照工作副本将 diff 应用回原提交默认对后代执行 rebase 传播--restore-descendants与--ignore-changes可改变这一行为子进程会获得JJ_WORKSPACE_ROOT、JJ_CHANGE_ID、JJ_COMMIT_ID三个环境变量cli/src/commands/run.rs。也就是说jj run已经在本地磁盘工作副本上实现了路线图中为命令廉价创建临时工作副本的雏形而 VFS 则是让这一能力更廉价、让大仓库工作副本更新更快的未来优化。相关测试见 cli/tests/test_run_command.rs。8. 更好的大文件支持目标与动机最后一项规划相对开放项目讨论过使用**内容定义分块CDCcontent-defined chunking**来降低大文件的存储与传输成本未来云端服务器上可能采用与 XetHub 存储类似的模型来存储文件。仓库中的现状从源码看当前仓库对大文件的应对仍以工作副本快照阶段的保护性限制为主。例如jj run的快照选项中硬编码了max_new_file_size: 64_000_u64即 64 MB见 cli/src/commands/run.rs用于限制新文件的追踪大小配置侧存在snapshot.max-new-file-size选项测试样例见 cli/tests/sample-configs/valid/snapshot.max-new-file-size_numeric.toml。而 CDC 分块存储、与 XetHub 类似的去重模型仍停留在讨论过的阶段。总结从路线图看 Jujutsu 的能力边界综合 8 项目标与仓库源码证据可以对 Jujutsu 的发展状态做如下收敛判断路线图目标当前状态基于仓库证据复制/重命名追踪已实质落地CopyId/CopyHistory/CopyRecord进入数据模型TreeValue::File携带copy_idCopiesTreeDiffStream与CopyHistoryDiffStream已实现Git 后端明确暂不支持追踪返回UnsupportedSimple/Secret 后端为空实现Forge 集成部分落地Gerrit 集成jj gerrit upload完整可用GitHub/GitLab 的submit命令尚无实现子模块支持早期阶段GitSubmodule(CommitId)已进入TreeValueSubmoduleStoretrait 仅有雏形分阶段设计文档在案更好的 Rust API进行中jj-lib架构完备但命令输出仍以 CLI 打印为主状态对象化重构未完成RPC API未动工无jj api命令属已立项规划开源云端仓库接口就绪、实现未开始backend trait 已为云后端预留查询抽象VFS未动工jj run已用本地磁盘临时工作副本实现等价场景的雏形大文件支持早期讨论仅有快照阶段的文件大小保护限制CDC/去重存储尚未实现这份路线图的价值在于它清晰地划定了 Jujutsu 的下一步。对于使用者和潜在贡献者最值得关注的是复制/重命名追踪已具备可验证的模型与实现雏形docs/design/copy-tracking.md 与 lib/src/copies.rs 是最好的阅读起点而子模块、RPC API 与云端仓库则仍在等待设计与实现者。由于路线图明确不承诺时间表任何功能的实际可用状态都应以当前仓库源码为准——本文给出的源码路径即为读者自查的索引。【免费下载链接】jjA Git-compatible VCS that is both simple and powerful项目地址: https://gitcode.com/GitHub_Trending/jj/jj创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📌 标签:
工业官网
设计趋势
AI 建站
SEO
获取完整报告 →
RELATED ARTICLES
推荐阅读
2026/9/11 13:48:22
Claudian Obsidian 插件完整安装指南:3 步让 Claude Code 住进你的笔记库
2026/9/11 13:48:22
CMSIS-6源码深度评测:迁移风险与工程化集成要点
2026/9/11 13:43:22
Flink SQL + Iceberg/Hudi:数据湖表格式集成与实时入湖实践
2026/9/11 16:49:02
WebHostView与TabHelper的深度对比与性能优化
2026/9/11 16:49:02
解决Matplotlib中文显示问题的全面指南
2026/9/11 16:49:02
MuJoCo 摩擦失效排查:物体仿真滑动的 4 个成因与修复路径
2026/9/11 16:49:02
Abaqus VUMAT三维损伤模型开发实战:从连续介质损伤力学到Fortran实现
2026/9/11 16:49:02
Open Notebook REST API 完全指南:调用方法、端点全解与源码级实践
2026/9/11 16:44:01
Umi 搭配 UnoCss 构建后样式丢失?三步改完的避坑指南
2026/9/11 0:02:03
数据容灾核心指标与实战方案解析
2026/9/11 0:02:03
Huly 平台 ClickUp 任务导入实战指南:从 CSV 导出到一键迁移全流程解析
2026/9/11 0:02:03
PyTorch 构建与代码生成工具链深度解析:从 tools 目录看懂构建流程、autograd/JIT 代码生成与 HIPify 移植
2026/9/11 5:40:15
超人会飞不算本事:系统稳定依赖清晰规则与边界设计
2026/9/11 8:29:24
超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论
2026/9/11 9:11:20
基于CNN的调制信号识别:MATLAB实现时频图分类实战