Git vs. Mercurial

GIT 在当年的 SubversionBitKeeperMonotoneArchBazaarMercurialDarcsFossil 版本控制系统纷争中脱颖而出,成为绝对主流,但对 Git 的质疑从未停止过,其复杂、繁多、晦涩的命令,奇怪的 staged area、stash、rebase、detached heads,难用的 submodule 和 partial clone、sparse checkout、LFSAnnexLOP,虽然这些年 Git 一直在改善,但要么积习难改繁上加繁,要么知者甚少依然晦涩,因此不断有人试图造轮子替代 Git,如 GotGitless,本文简要介绍三个有潜力的替代品 JujutsuSaplingPijul,它们不仅仅是对 Git CLI 的简化,而是从使用流程、思维上有了很大革新,其中 Jujutsu 和 Sapling 支持 Git 存储格式和网络协议,但 UI 体验向 Mercurial 靠齐,也可以一定程度上说 Mercurial 赢在了最后!

  • Google 的版本管理工具变迁: CVS → Perforce → Piper → CitC + Piper → CitC + Piper + Mercurial (aka. Fig) → CitC + Piper + jj (aka. Fig NG);
  • Facebook 的版本管理工具变迁: Subversion → Git → Mercurial → 重写的 Mercurial server + hg watchman + hg EdenSC + hg absorb → Sapling;

Jujutsu (jj)

  • 主页: https://jj-vcs.github.io/jj/latest/
  • 作者: Martin von Zweigbergk, 2011 加入 Google,2014 全职开发 Jujutsu
  • 受启发:Git, Piper + CitC, Mercurial, Sapling, Darcs
  • 开源时间: 2020-12
  • 实现语言:Rust

Google 的下一代版本管理工具,与 Git 兼容,主要改进:

  1. 极大简化模型
    1. 去掉了 staged area、stash、detached heads 概念,将工作区直接视为一个可操作的提交,消除了 Git 中索引(暂存区)的复杂性,是更优雅、更一致的设计;
    2. 弱化了 branch 概念,不再必须创建分支,分支管理接近 Mercurial;
    3. 工作目录即提交,简化了 dirty files 管理,再也不用担心丢文件、丢修改、stash 混乱;
    4. 将冲突本身作为数据结构存储,允许用户先提交冲突状态,之后再解决,避免了 Git 中 rebase --continue的中间状态,使操作更具原子性
  2. git rebase -i 更强大方便的提交历史改写能力,促成 Git 增加了试验性的 git replay 命令
    1. 引入稳定的 Change ID,再也不用烦恼 rebase 后 Commit ID 变化;
    2. 改写历史后自动 rebase 后续提交,管理 stacked commits 更方便;
    3. jj splitjj movejj amend等命令提供了比 Git 更灵活、更强大的方式来拆分、移动和修改提交,即使是历史提交也能轻松处理;
  3. Git reflog 相比,Jujutsu 的操作日志(jj op)将复杂操作视为单个原子条目,使得 jj undo命令非常强大和可靠,极大地降低了误操作导致数据丢失的风险;
  4. Git revisions 更强大方便的 revsets 语法(源自 Mercurial);
  5. 底层存储与 Jj 上层命令实现解耦,Git 是目前最成熟的底层存储;

所谓的 stacked commits/changes/diffs、stacking 指 https://www.stacking.dev/ 所描述的工作流:下一个 feature branch B 可以依赖还没完成代码评审的 feature branch A,并在 feature branch A 有变更时能自动 rebase feature branch B 和更新对应的 pull request。这个工作流需要两方面能力的配合:(1) 在 local repo 里自动 rebase 下游分支,例如 git rebase --update-refs,Jujutsu、Sapling、Pijul 也都支持这个特性;(2) 自动创建、更新多个 feature branches 所对应的 pull requests,例如 SaplingGit TownsprGhstackrevupGraphite(不开源)。

Jujutsu 的 working copy as commit 设计默认会提交所有文件,这对习惯了 git add 的人可能很不适应,可以用如下方法之一解决:

  1. 【不投荐】用 jj config set --repo snapshot.auto-track 'none()' 以及 jj file track xxx显式增加文件,用 jj splitjj commit -i 达到 git add -i/-pgit commit --interactive/--patch 的效果;
  2. .gitignore 里增加一个 tmp 目录用作 scratch area,用于存放无需版本管理的文件,并用 jj file untrack xxx 来去掉失误提交的文件,用 jj splitjj commit -i 达到 git add -i/-pgit commit --interactive/--patch 的效果;

注意截止 2025-10 Jujutsu 还不支持 Git submodule,而 Sapling 支持

Sapling

  • 主页: https://sapling-scm.com/
  • 作者:Meta(原 Facebook)
  • 受启发:Mercurial
  • 开源时间:2022.11(实际开发时间开始自 2005.4)
  • 实现语言:Rust

Meta 的下一代版本管理工具,与 Git 兼容,主要改进:

  1. 对巨型单库 partial clone、sparse checkout 的良好支持(已回馈给 Git,Microsoft 也贡献了 Scalar);
  2. 对 stacked commits 管理的良好支持,且支持管理 stacked PRs;
  3. 弱化了 branch 概念,不再必须创建分支,分支管理接近 Mercurial;
  4. 去掉了 staged area 概念;
  5. 更强大方便的 undo 能力;
  6. 支持 sparse profile 方便同组的同事工作在同一个文件集合上;

Pijul

不兼容 Git,不是基于快照而是基于补丁,天然方便 stacked commits 的管理,UI 比 Git、Jujutsu 和 Sapling 更简洁,有更好的多路合并正确性

快速入门

Sapling 的 Git 桥接思路主要是改进 Git 使用体验,可以认为是个更好的 Git client,而 Jujutsu 要激进点,目标是下一代的 DVCS,只是目前开源的存储后端是 Git。 两者都能很方便的与 Git 一起使用。

Jujutsu:

brew install jj         # on macOS

# 克隆 Git 库
jj git clone URL
# or 在已有的 Git work copy 里
jj git init

jj help

进一步使用见 Jujutsu 教程: https://jj-vcs.github.io/jj/latest/tutorial/

Sapling:

brew install sapling      # on macOS

# 不要用 sl clone 和 sl init,这个模式不能与 Git 一起使用
git clone URL

sl help

进一步使用见 Sapling 教程: https://sapling-scm.com/docs/introduction/getting-started

参考

  1. Jujutsu: a new, Git-compatible version control system
  2. Is Git Finally Getting a Successor? Jujutsu (jj), Sapling, and Pijul for Stacked Diffs and Monorepos in 2025
  3. Ask HN: Git Alternatives – Sapling vs. Jj 这篇提到一个介于 Git 和 Jujutsu/Sapling 之间的工具 git-branchless
  4. Ask HN: on Steve’s Jujutsu Tutorial
  5. https://en.wikipedia.org/wiki/Comparison_of_version-control_software