Jujutsu 使用手册(附 Git 对比)

理解 Jujutsu 的核心概念

Jujutsu 是一个与 Git 兼容的版本控制系统,旨在简化复杂工作流的同时保留 Git 的强大功能。其架构与 Git 在几个关键方面存在根本差异,使其在许多开发场景中更直观易用。

与 Git 的核心差异

Jujutsu 完全消除了暂存区的概念。工作目录中的所有更改都会自动跟踪为当前变更的一部分,无需使用 git add 命令。冲突被视为一等对象,可以提交、共享和协作解决,这与 Git 要求在提交前解决冲突的方式不同。

操作日志全面记录了每个命令的执行情况,提供了精确的撤销功能,超越了 Git 的 reflog 能力。历史操作更加灵活,允许更改自由重排、修改或合并,不受严格的线性约束。

Revset 符号参考

Jujutsu 使用功能性 revset 语言来选择提交。@ 表达式指代当前工作区中的工作副本提交。基本符号包括:

  • @ - 当前工作副本提交(相当于 Git 的 HEAD)
  • @- - 工作副本的父提交
  • @+ - 工作副本的子提交
  • ::@ - 工作副本的所有祖先,包括 @ 本身
  • @:: - 工作副本的所有后代,包括 @ 本身
  • @.. - 除 @ 的祖先外的所有提交
  • :: - 仓库中所有可见的提交
  • ~ - 集合补集(否定运算符)
  • & - 集合并集
  • | - 集合交集

仓库设置

克隆与初始化

对于 Git 后端仓库,使用 jj git clone <url> 创建新仓库。对于与现有 Git 仓库共存的模式,使用 jj git init --colocate

# Git 后端仓库
jj git clone https://github.com/user/repo

# 与现有 Git 仓库共存
git clone https://github.com/user/repo && cd repo && jj git init --colocate

# 初始化新的 Git 后端仓库
jj git init

基本工作流命令

仓库状态与历史

# 检查仓库状态
jj status  # 或简写 jj st

# 查看提交历史
jj log

# 查看所有提交,包括隐藏的
jj log -r ::

创建和管理变更

jj commit 命令更新描述并在顶部创建新变更。变更会自动跟踪,无需显式暂存。

# Git 工作流
git add file.txt
git commit -m "更新文件"

# Jujutsu 工作流
jj commit -m "更新文件"  # 自动包含所有变更

# 替代方案:仅描述当前变更而不创建新变更
jj describe -m "更新文件"

修改变更

# Git
git commit --amend

# Jujutsu - 将工作副本变更合并到父提交
jj squash

# 更新提交消息
jj describe -m "更新的消息"

书签管理

Jujutsu 使用"书签"(bookmarks)代替分支 - 它们是指向提交的轻量级指针。

# 从当前变更创建书签
jj bookmark create feature-name

# 从特定提交创建书签
jj bookmark create bugfix -r <commit-hash>

# 列出所有书签
jj bookmark list

# 删除书签
jj bookmark delete feature-name

在变更间导航

# 切换到特定书签或提交
jj edit <bookmark-name>
jj edit @-  # 切换到父提交

# 从特定提交创建新变更
jj new <commit-hash> -m "新变更描述"

差异比较

# 当前工作副本的变更
jj diff

# 特定版本之间的差异
jj diff --from <rev1> --to <rev2>

# Git 风格的输出格式
jj diff --git

远程操作

获取和推送

使用 jj git fetch 从远程获取,使用 jj git push 并加上 --bookmark 推送特定书签。

# 从远程获取
jj git fetch

# 推送特定书签
jj git push --bookmark feature-name

# 推送到特定远程
jj git push --remote origin --bookmark feature-name

整合远程变更

# 获取并将当前变更变基到远程 main
jj git fetch
jj rebase -d main@origin

高级操作

撤销功能

jj undo 命令创建一个新操作,用于撤销先前的操作。使用 jj operation log 查看操作日志。

# 撤销上一个操作
jj undo

# 查看操作历史
jj operation log  # 或简写 jj op log

# 恢复到特定操作
jj operation restore <operation-id>

变基操作

jj rebase 命令将修订移动到不同的父提交,同时保留变更。

# 将当前变更变基到 main
jj rebase -d main

# 变基特定修订
jj rebase -s <源> -d <目标>

# 变基多个修订,同时保留依赖关系
jj rebase -r <revset> -d <目标>

创建合并提交

# 创建具有多个父提交的合并提交
jj new main feature -m "将 feature 合并到 main"

冲突解决

Jujutsu 允许提交和共享冲突,支持协作解决。

# 查看有冲突的提交
jj log -r 'conflicts()'

# 手动解决冲突后,变更会自动整合
# 创建新变更以继续工作
jj new

文件操作和配置

文件历史和模式

# 查看修改特定文件的提交
jj log -r 'files("filename")'

# 设置用户配置
jj config set --user user.name "你的名字"
jj config set --user user.email "you@example.com"

高级 Revset 示例

Revsets 提供了强大的提交筛选功能。

# 不在任何远程书签上的提交
jj log -r 'remote_bookmarks()..'

# 特定作者的提交
jj log -r 'author("name@example.com")'

# 描述中包含特定文本的提交
jj log -r 'description("bug fix")'

# 合并提交
jj log -r 'merges()'

# 修改特定文件模式的提交
jj log -r 'files("src/**")'

关键行为差异

自动变更跟踪

与 Git 的暂存区方法不同,Jujutsu 自动将所有工作目录修改纳入当前变更,通过消除手动暂存步骤简化了开发工作流。

全面的操作日志

操作日志记录每个命令的执行,而不仅仅是引用更新,提供了比 Git 的 reflog 更精细的撤销能力。

冲突处理理念

Jujutsu 将冲突视为可提交、可共享的对象,支持分布式冲突解决工作流,这是 Git 的提交前解决要求无法实现的。

工作副本模型

工作副本与特定变更 ID 保持直接关联,修改会自动成为该变更的一部分,提供了工作目录状态和仓库历史之间的无缝集成。

这种方法消除了 Git 中工作目录、暂存区和仓库之间的概念复杂性,同时保持与 Git 仓库和工作流的完全兼容性。