「再也不用為 rebase 崩潰了。」
這是許多開發者在第一次使用 Jujutsu (jj) 後的共同心聲。

Git 改變了世界,但也留下了無數「分支地獄」的故事。今天,我們將從兩個被低估的 Git 外掛工具開始,一步步引導你走向一個更現代、更人性化的版本控制未來 —— Jujutsu (jj)


引言:Git 的輝煌與隱憂

你是否曾經:

  • 為了改一個 typo,敲了 git rebase -i HEAD~5,然後工作目錄瞬間爆炸?
  • 在 10 個依賴分支之間切來切去,忘記自己正在做什麼?
  • 看著 git log 像聖誕樹一樣亂七八糟,卻無從下手?

Git 無疑是偉大的,但它的設計來自 2005 年。那個年代沒有 stacked diff、沒有 PR stack、沒有即時 CI。
今天,我們需要的不只是「能用」,而是「好用」。

這篇文章將帶你走過一條進化之路

graph LR A[git-revise] --> B[git-branchstack] --> C[Jujutsu] style C fill:#6c5ce7,stroke:#333,color:#fff style A fill:#fab1a0 style B fill:#fdcb6e

從小修小補,到系統性革新。


第一站:git-revise —— 讓歷史編輯不再「破壞」

問題:git rebase 的副作用

$ git rebase -i HEAD~3
# 衝突!工作目錄被打斷,stash 忘記了,崩潰中...

rebase 雖然能重寫歷史,但它會強制中斷你的工作流

graph TD subgraph "Git rebase 問題" A[工作目錄] --> B[rebase 開始] B --> C[衝突中斷] C --> D[stash / reset] D --> A end style C fill:#e17055,stroke:#333,color:#fff

圖1:傳統 git rebase 常導致工作流循環中斷


解法:git-revise

git-revise 是 Git 的子命令,專注於非破壞性提交編輯。它在記憶體中操作,不影響工作目錄

# 安裝
pipx install git-revise

# 修復最近一個 commit 的拼字錯誤
git revise -m "Fix typo in login button"

# 分割最後一個大 commit 成兩個小塊
git revise --split
graph LR subgraph "git-revise 流程" A[記憶體中編輯] --> B[更新 commit] B --> C[工作目錄不變] C --> A end style B fill:#00b894,color:#fff

圖2:git-revise 在記憶體中安全編輯,工作流不中斷

靈感來源git-revise 是 jj 創始人 Martin von Zweigbergk 早期作品之一。

它讓「修補歷史」從痛苦變成愉悅,但它只解決了單點問題。分支管理呢?還是一團亂。


第二站:git-branchstack —— 分支堆疊的魔法

問題:分支依賴地獄

# 手動流程
git checkout main
git checkout -b feature/login
# ... coding ...
git checkout -b feature/login-validation  # 依賴 login
git checkout feature/login
# 切來切去,build 重跑,頭暈

在團隊使用 stacked diff(如 Gerrit、Phabricator)時,這種切換簡直是災難。

graph TD A[main] --> B[feature/login] B --> C[feature/login-validation] C --> B B --> D[feature/other] style B fill:#fd79a8 style C fill:#fd79a8 style D fill:#fd79a8

圖3:傳統 Git 分支切換形成雜亂的依賴網


解法:git-branchstack

這是一個輕量級堆疊分支管理器,核心概念:

用 commit message 的 [topic] tag 自動建立分支堆疊

安裝

pipx install git-branchstack
pipx install git-revise  # 建議一起用

實戰範例

假設你在 local-dev 分支上有 3 個 commits:

# 用 git-revise 加上 topic tags
git revise --interactive --edit

編輯後的 commit message:

[auth] Add login endpoint
[auth] Validate JWT token
[ui] Update login button style

執行:

git branchstack
gitGraph commit id: "main" branch auth checkout auth commit id: "Add login" commit id: "Validate JWT" branch ui checkout ui commit id: "Update button"

圖4:git branchstack 自動建立清晰的堆疊結構

推送整個堆疊

# 設定 alias 更方便
git config alias.bspush '!git push -u origin $(git branchstack --list-local)'

git bspush

來源:git-branchstack GitHub

它讓「分支堆疊」從手動變成自動,但它仍是 Git 的外掛,無法改變核心體驗。


高潮:Jujutsu (jj) —— 版本控制的未來已來

jj = git-revise 的靈魂 + git-branchstack 的堆疊 + Git 的相容性 + 全新設計

由 Google 工程師 Martin von Zweigbergk 開發,jj 已在 Google 內部逐步取代舊 VCS。

核心創新對比

概念 Git jj
提交單位 不可變 commit 可變 change
歷史追蹤 線性 log 操作日誌 (operation log)
分支管理 手動切換 自動書籤 + 堆疊
衝突處理 手動 內建多方解析器
相容性 - 100% Git 互通
graph LR subgraph "jj 核心模型" C[Change] --> O[Operation Log] C --> B[Bookmarks] B --> G[Git 互通] end style C fill:#6c5ce7,color:#fff

圖5:jj 的 changes + bookmarks + operation log 核心架構


關鍵特性一:Changes 而非 Commits

# jj:提交是「活的」
jj new               # 創建新 change
echo "fix" >> file   # 修改
jj amend             # 更新當前 change(像 git amend)
jj split             # 輕鬆分割 change
graph LR A[原始 change] --> B[jj amend] B --> C[更新後 change] C --> A style B fill:#00b894,color:#fff

圖6:jj amend 即時更新 change,無需 rebase

所有操作都在記憶體中,不中斷工作流


關鍵特性二:操作日誌 (Operation Log)

jj op log
@  abc123  2分鐘前  new change
├─ def456  5分鐘前  amend change
├─ ghi789  10分鐘前 rebase -d main
graph TD A[rebase -d main] --> B[amend change] B --> C[new change] style C fill:#6c5ce7,color:#fff

圖7:jj op log 提供完整操作歷史,永不迷路

你永遠知道「系統怎麼變成這樣的」。


關鍵特性三:自動堆疊書籤(進階版)

# 從 main 開始
jj new main -m "[auth] Add login"
jj bookmark create auth   # 手動標記(僅此一次)

# 繼續堆疊
jj new -m "[ui] Update button"
jj bookmark create ui     # 標記上層

jj log 顯示

$ jj log
@  ooo  [ui] Update login button
│  │   (你正在編輯)
├─ ooo  [auth] Add login endpoint
│  │
○──○──○ main
gitGraph commit id: "main" branch auth checkout auth commit id: "Add login" branch ui checkout ui commit id: "Update button" checkout main

圖8:jj log 內建堆疊視覺化,無需額外工具

小提醒:bookmark 需手動 create,但一旦建立,後續 amend/rebase自動移動上層,無需手動調整。

推送整個堆疊

jj git push --all-bookmarks

對比:Git vs jj 的 rebase

動作 Git jj
重新基於 main git rebase main jj rebase -d main
工作目錄中斷?
歷史可回溯? 靠 reflog 內建 op log
分支堆疊保留? 手動 自動
graph LR subgraph "Git rebase" G1[main] --> G2[feature] G2 --> G3[rebase 後] style G3 fill:#e17055 end subgraph "jj rebase" J1[main] --> J2[auth] J2 --> J3[ui] J3 --> J4[自動調整] style J4 fill:#00b894,color:#fff end

圖9:jj rebase 自動調整堆疊,Git 需手動修補


實戰:30 秒上手 jj

# 1. 安裝(需要 Rust)
cargo install jj

# 2. 從現有 Git repo 啟動
cd my-project
jj git init

# 3. 開始使用
jj log
jj new -m "fix typo"
echo "hello" >> file
jj amend
jj git push
graph TD A[安裝 jj] --> B[初始化 repo] B --> C[開始使用] C --> D[無痛 amend] style D fill:#6c5ce7,color:#fff

圖10:從 Git 遷移到 jj 的 3 步流程

官方文檔:github.com/jj-vcs/jj


結論:擁抱進化,別讓工具綁住你

工具 定位 適合對象
git-revise 局部修補 想提升 rebase 體驗
git-branchstack 堆疊管理 stacked diff 團隊
Jujutsu (jj) 全面替代 追求未來 VCS 的人
graph TD A[痛苦的 Git 日常] --> B[嘗試 git-revise] B --> C[愛上 git-branchstack] C --> D[擁抱 Jujutsu] style D fill:#6c5ce7,stroke:#333,color:#fff

git-revise 的小修小補,到 git-branchstack 的分支魔法,jj 將這些碎片融為一體,開啟版本控制的新紀元。

下次 rebase 讓你崩潰時,試試 jj

你不會想回去的。


行動呼籲

  1. 現在就試試:cargo install jj
  2. 從你的 Git repo 匯入:jj git init
  3. 留言分享你的第一個 jj amend 體驗!

本文作者使用 jj 撰寫,無 rebase 崩潰,僅有快樂。


Mermaid 圖表說明

  • 所有圖表皆使用 mermaid 語法,支援 GitHub、Notion、Typora、Obsidian 等平台即時渲染
  • 無需外部圖片,純文字即可呈現專業視覺效果
  • 可複製到任何支援 Mermaid 的編輯器中查看

立即發布建議

  • GitHub / GitLab:直接支援 Mermaid
  • Notion:貼上 ```mermaid:disable-run
  • Medium / Dev.to:需啟用 Mermaid 插件或嵌入 CodePen
  • 個人部落格:使用 Hugo + mermaid 插件或 VitePress

全純 Markdown + Mermaid,零圖片依賴,極致可讀!