LWN:介绍jujutsu——跟Git兼容的版本控制工具!

关注了就能看到更多这么棒的文章哦~

Jujutsu: a new, Git-compatible version control system

By Daroc Alden
January 19, 2024
ChatGPT translation
https://lwn.net/Articles/958468/

Jujutsu 是一个由 Martin von Zweigbergk 于 2019 年作为个人爱好项目创建的跟 Git 兼容的分布式版本控制系统。它旨在成为一个更简单、性能更高、更易于使用的 Git 替代品。Jujutsu 拥有一个彻底简化的用户界面,并集成了基于 patch 的版本控制系统中的想法,以便采用新颖地方法来解决合并冲突。它是用 Rust 编写的,可在 Apache 2.0 许可下使用。

与其他基于 Git 的项目(例如 Gitless 或 Magit)不同,Jujutsu 在设计时就考虑了最终摆脱对 Git 的依赖。Jujutsu 的代码本身是用 Rust 编写的,但它链接了 libgit2(核心 Git 功能的 C 语言实现)以与 Git 仓库进行交互。Jujutsu 可以使用 Git 仓库作为其存储后端,或使用其自己的自定义存储后端。原生后端尚未准备好投入使用。该项目的 README 中指出:“后端主要是用于确保最终能够添加无法轻松添加到 Git 后端的功能”。现在由 Google 资助从事该项目的 Von Zweigbergk 计划为 Jujutsu 扩展一个面向 Google 内部基于云的存储的后端(如 他的 2022 年 Git Merge 演讲幻灯片 中所示)。Jujutsu 被设计为惰性地从其存储后端获取信息,特别是为了支持大型 monorepos,例如 Google 使用的主要场景。

目前,Jujutsu 致力于成为一个简单的 Git 替代品,用于日常工作流。核心贡献者使用它来处理 Jujutsu 仓库,而不会遇到重大问题。然而,该项目仍然缺乏对 Git 的一些更高级特性的支持,包括子模块、部分克隆、浅克隆、多个工作树、稀疏检出、签名提交和 Git Large File Storage (LFS)。

此外另一个困难之处在于缺乏对 挂钩(hook) 的支持,也就是可以在 Git 操作的不同点上调用的外部脚本。Git 曾经有很多用 shell 脚本编写的组件,使其能够轻松添加要针对各种操作调用的挂钩。即使许多核心组件已重写为 C,Git 也始终保持向后兼容,主要是针对调用挂钩的时间。Git 贡献者 Elijah Newren 指出该问题 是改进 Git 的 rebase 操作性能的难点之一。

计划在 Jujutsu 中添加对一部分挂钩的支持,但这比看起来的更困难。与 Git 不同,Jujutsu 旨在让所有操作直接针对底层存储运行,并在事后将任何必要的更改生成到文件系统中去。这个选择允许 Jujutsu 在裸存储库中使用相同的命令工作,并在不触及文件系统的情况下执行更有效率的内存内转换,但这使得支持挂钩变得具有挑战性。由于挂钩是外部程序,它们通常期望通过文件系统与存储库进行交互,而在内存中直接执行操作时则不可能做到这一点。这个不足之处也意味着 Jujutsu 无法配置使用不同的合并策略。

Jujutsu 从一开始就注重性能的设计意味着它可以用比 Git 快得多的速度完成 rebase 操作。Jujutsu 的优异性能促使 Elijah Newren 和 Christian Couder 提议一项“=git replay=”的新命令,使 rebase 操作更快。它实现这一点的部分方式是通过采用合理默认值(例如,使相当于“–reapply-cherry-picks”的值成为默认值),部分是通过尽可能避免像“git rebase”那样遍历 commit graph 来实现。在首次引入“git rebase”时,遍历 commit graph 以获取会减少所需合并次数的额外信息是一种合理的性能优化,但现在其他有关合并的性能改进已经让这种权衡在大多数情况下都不再值得。尽管“git replay”比“git rebase”有显著提升,但与 Jujutsu 的 rebase 操作相比仍然落后。

  • 功能

    Jujutsu 还有其他几个方面不同于 Git。最引人注目的一点可能是删除了暂存区(index)。在 Jujutsu 中,工作树由实际提交直接表示。可以通过直接编辑磁盘上的文件来编辑该提交,而无需暂存或取消暂存。运行 Jujutsu 命令将在执行其他操作之前将来自文件系统的所有更改复制到工作提交中。若要最终完成提交并停止编辑,用户只需在旧提交之上使用“jj new”创建一个新工作提交。由于工作副本是与其他副本一样的提交,因此 Jujutsu 不需要像“git add”或“git stash”之类的修改暂存区的命令。

    Jujutsu 中的大多数命令默认会影响工作副本,但可以通过指定它们的修订版本来对其他提交执行相同的操作。例如,“jj describe”用于更改提交的消息。如果在没有任何其他参数的情况下调用它,它会更改工作副本的提交消息。如果使用另一个修订版本调用它,它会更改历史提交的提交消息,并透明地对所有依赖于它的内容进行 rebase。其他命令,例如“jj move”(可在提交之间移动差异),也是遵循同样的原则。

    这种自动地 rebase 提交的做法虽然很方便,但也自身会带来一堆问题,尤其是在 rebase 那些已发送给其他开发人员或是发送到中心化服务器的提交的时候。为了减少隐式 rebase 产生的各种冲突,Jujutsu 使用了来自基于补丁的版本控制系统(例如 Darcs 和 Pijul) 的一个创意。这些系统允许任何人提交冲突并在之后解决冲突。这个过程不涉及对文本冲突标记进行提交,而是使用冲突树的表述形式。这样的话就可以在之后的提交当中解决冲突了。

    冯·茨韦伯格 给出了一个关于如何运作的示例。考虑如下的 Git 历史记录,类似于这样:

    o---*---o topic
             /
    o---o---o---*---o---o main

    以星号标记的两个提交具有互相冲突的改动。此代码的作者想要将 main 分支合并到 topic 分支,解决合并冲突,然后在稍后将 topic 分支 rebase 到 main 分支,从而消除不必要的合并。使用 Git 时,作者可以使用 "git rerere" 来记住这次的冲突解决方式(conflict resolution),并在 rebase 时重新应用。使用 Jujutsu 时,他们可以简单地 rebase 到 main 分支的上面并修复冲突,得到以下历史记录:

    o---*---o---+ topic
                                 /
    o---o---o---*---o---o---o---o   main

    现在,如果作者使用 “jj log” 检查此历史记录,他们会看到标记在 topic 分支上的以星号标记的提交被标记为具有冲突,其后的提交亦是如此。带有加号的提交是解决冲突的提交。在稍后,如果他们想要清除其历史记录,则可以将冲突解决移入最初出现问题的提交中,并获得一个干净的线性历史记录,通过使用如下命令:

    jj move --from <plus commit> --to <star commit>

    通过这种方式存储冲突信息,Jujutsu 可以确保合并和 rebase 始终“成功”——可能会留下一些冲突的代码树,可以在之后进行处理。冲突的树可以像普通树一样提交、检出和编辑。冲突文件呈现为 Git 在合并失败后添加的文本冲突标记,但内部表示为一系列差异。存储冲突的方法可能无法有效发挥作用的用例之一是二分查找,因为冲突提交可能无法正确完成编译。计划增加二分查找支持,但实现尚未最终确定。以这种方式表示冲突的一个优点是 Jujutsu 不需要“git rebase –continue”的等效项。每次 rebase 和每次合并都在一个命令中完成,而不会在中间停止以寻求帮助,Git 就容易出现这样的情况。

    这就引出了 Jujutsu 的重要功能:操作日志(the operation log)。像 Git 的 reflog 一样,操作日志跟踪存储库的先前状态。与 reflog 不同,操作日志将 rebase 或其他复杂操作视为单个原子项目。然后,操作日志为“jj undo”命令提供支持,该命令可以撤消任何其他 Jujutsu 命令的效果。

    快速、原子、普遍的 rebase 组合在一起提供了管理存储库的新的愿景。Jujutsu 的用户体验最终是否得到改善还有待观察,尽管其设计的根本的简约性非常令人期待。

  • 体验 Jujutsu

    虽然 Jujutsu 尚未针对大多数发行版进行打包(不讨论 NixOS ),但有兴趣尝试的读者可以下载 预编译版本 或编译 源代码. 使用 Jujutsu 克隆现有 Git 存储库的操作是使用“jj git clone”完成的。克隆包含许多 ref 的 Git 存储库可能会很慢,Jujutsu 文档警告说,同时使用 Git 和 Jujutsu 的混合存储库可能会看到 Jujutsu 命令运行缓慢,因为需要检查 Git ref 以了解命令之间的更改。

    命令行接口与 Git 非常相似,除了省略了用于操作 index 的命令。需要注意的一个不同之处是“jj log”默认仅显示本地提交。要显示存储库的完整历史记录,可以使用以下命令:

    jj log -r 'all()'

    Jujutsu 文档具有 全面的介绍 和 Git 命令和 Jujutsu 命令之间的比较.

  • 结论

    Jujutsu 在短短几年内取得了很大进展。它已经可用于处理不需要更复杂的 Git 特性的项目,并且提供了体验类似的用户界面、一些操作上更好的性能表现,以及解决冲突的有趣方法。在 Google 的持续支持下,Jujutsu 似乎有望继续积极开发。

    与此同时,Jujutsu 缺少了 Git 中的一些能够灵活适应不同用例的特性,例如挂钩 hook 或子模块 submodule。从 Git 导入许多 ref 仍然很慢,并且仍然存在一些在存储库最初设置上的不舒服的地方。Jujutsu 是否在 Google 外部得到使用取决于它的简化界面是否能够克服其对不常见工作流的可适用性降低的问题。

    全文完
    LWN 文章遵循 CC BY-SA 4.0 许可协议。

    欢迎分享、转载及基于现有协议再创作~

    长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

    bb44a54c8d3cccebe6d789a4faa0579a.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值