試用 Gemini 3 Pro
我使用 Gemini 3 Pro 和 Antigravity IDE 建立了 https://github.com/p47t/rec.2020 。你可以在 https://p47t.github.io/rec.2020/ 查看已建立的應用程式。
以下是建構 https://github.com/p47t/rec.2020 的過程:
專案初始化 :我首先要求 Gemini「建立一個視覺化 Rec.2020 色域的 web 應用程式」。它立即使用基本的 canvas 實作建立了專案檔案。
改進 :接著我要求更多改進來優化使用者介面。
互動功能 :為了讓它更實用,我請求「在滑鼠移動時顯示座標」,Gemini 完美地實作了這個功能,並正確處理了座標轉換。
色彩準確度 :我還要求修正不正確的 sRGB 色域檢查,並繪製 sRGB 三角形以便於驗證。Gemini 理解色彩科學的需求,並實作了正確的數學轉換,以便在 Rec.2020 空間內顯示 sRGB 三角形。
部署 :最後,我要求一份「部署指南」,它便生成了一份包含詳細說明的 DEPLOY.md。
錯誤修復 :我發現了另一個由畫布縮放顯示引起的問題,導致顏色選擇不準確。Gemini 識別出了問題,並修復了座標計算以支援調整視窗大小。
整個過程非常順暢。我幾乎不需要寫任何樣板程式碼。Gemini 3 Pro 同樣出色地理解高層次的意圖和複雜的領域知識(如色彩空間)。
Git 的痛點到未來:Jujutsu (jj) 版本控制系統的進化之旅
AI 生成聲明: 本文初稿由 Gemini 2.5 Flash AI 生成, 再由個人手動修改而成。
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。
你不會想回去的。
行動呼籲 :
現在就試試:cargo install jj
從你的 Git repo 匯入:jj git init
留言分享你的第一個 jj amend 體驗!
本文作者使用 jj 撰寫,無 rebase 崩潰,僅有快樂。
版本控制的個人效率追尋:從 git-revise、git-branchstack 到 Jujutsu
AI 生成聲明: 本文初稿由 Claude AI Sonnect 4.5 模型 生成, 再由個人手動修改而成。
前言:Git 工作流的痛點
當我們使用 Git 進行開發時, 經常會遇到這些情況:
想修改歷史 commit, 需要用 git rebase -i 進入互動模式
管理多個相關的 feature branches, 需要手動追蹤分支間的依賴關係
不小心改錯了想回到之前的狀態, 得靠 git reflog 救援
Commit 之後才發現忘記加檔案, 又要 git commit --amend
這些操作雖然強大, 但往往需要記住複雜的命令組合, 對新手不友善。更重要的是, 它們打斷了開發者的思考流程, 讓人把注意力從「解決問題」轉移到「操作工具」。
對於追求高效工作流的開發者來說, 這些摩擦累積起來是不可忽視的時間成本。於是, 一些人開始探索更符合自己工作習慣的版本控制方式…
第一步:git-revise — 簡化歷史編輯
誕生背景
git-revise 是為了解決 git rebase -i 的複雜性而生。對於經常需要修改 commit 歷史的開發者來說, 互動式 rebase 的流程實在太繁瑣了。git-revise 提供了更直接的方式來達成同樣的目標。
核心特點
# 傳統 git rebase 的方式
git rebase -i HEAD~3 # 進入編輯器, 標記 edit/reword/squash...
# git-revise 的方式
# 1. 先修改檔案
vim some_file.py
# 2. Stage 你的修改
git add some_file.py
# 3. 應用到目標 commit
git revise # 將 staged changes 應用到該 commit
優勢
更安全 : 自動保留原始狀態,隨時可以恢復
更直覺 : 直接操作目標 commit,不需要互動式編輯器
避免衝突 : 智能處理 commit 間的依賴關係
限制
仍然基於 Git 的 branch 模型
無法徹底解決多分支管理的複雜性
第二步:git-branchstack — Branchless 工作流的個人實踐
為什麼需要它?
許多開發者發現, 傳統的「一個 feature 一個 branch」模式在實際工作中很不順手:
每次切換 branch 都要重新 build
多個相關的 PR 需要手動維護依賴關係
在不同 branch 間來回跳轉打斷思緒
git-branchstack 是一個個人效率工具, 讓你能用更自然的方式工作: 所有開發都在一個 branch 上進行, 只在需要提交 PR 時才生成對應的分支。
問題場景
你想在單一分支 上開發多個功能, 每個功能對應一個 PR:
功能 A: 重構 authentication
功能 B: 新增 profile 頁面 (依賴 A)
功能 C: 一個無關的 bugfix
傳統做法需要:
為每個功能建立獨立分支
在分支間來回切換
每次切換都重新 build, 浪費時間
手動管理分支間的依賴關係
git-branchstack 的創新解法
git-branchstack 讓你留在本地分支 , 用 commit message 的標籤來標記主題:
# 在本地分支上正常開發
git commit -m "[auth-refactor] Update login logic"
git commit -m "[auth-refactor] Add JWT support"
git commit -m "[profile-page:auth-refactor] Add profile component"
git commit -m "[bugfix-123] Fix memory leak"
# 一行命令生成所有分支
git branchstack
這會自動生成:
* local-branch (HEAD)
| - [bugfix-123] Fix memory leak
| - [profile-page:auth-refactor] Add profile component
| - [auth-refactor] Add JWT support
| - [auth-refactor] Update login logic
|
|-- bugfix-123 (branch)
| - Fix memory leak
|
|-- profile-page (branch)
| - Add profile component
| (based on auth-refactor)
|
|-- auth-refactor (branch)
- Add JWT support
- Update login logic
核心概念
標籤語法 : [topic] 或 [topic:dependency]
[auth-refactor] - 獨立主題
[profile:auth-refactor] - profile 依賴 auth-refactor
Branchless 開發體驗 :
所有工作在一個分支上進行
不需要切換分支, build 不會失效
修改任何 commit 後, 重跑 git branchstack 更新所有分支
利用 git-revise :
底層使用 git-revise, 不碰工作目錄
速度快, 不影響正在進行的工作
實際工作流
# 1. 開發階段 - 在本地分支上自由開發
git commit -m "[feature-A] Implement part 1"
git commit -m "[feature-A] Implement part 2"
git commit -m "[feature-B:feature-A] Build on A"
# 2. 需要修改之前的 commit
git revise --interactive --edit # 編輯 commit message 加標籤
git revise # 或直接修改內容
# 3. 生成/更新分支用於 PR
git branchstack
# 4. 推送到 GitHub
git push origin feature-A
git push origin feature-B
優勢與限制
優勢 :
真正的 branchless 體驗, 留在本地分支工作
自動處理依賴關係
支援 git rerere 記住衝突解決方案
永不修改工作目錄, 不影響 build
限制 :
需要在 commit message 中手動標記主題
依賴關係的改變需要修改 commit message
作者本人已轉向 Jujutsu (根據 git-branchstack README , 作者表示 jj 提供了更乾淨和強大的解決方案)
革命性轉變:Jujutsu (jj) — 重新定義個人版本控制體驗
為什麼誕生?
即使有了 git-revise 和 git-branchstack 這些工具, Git 的基礎模型仍然存在根本性的摩擦。Jujutsu 的作者 Martin von Zweigbergk (同時也是 Google 內部版本控制系統的開發者) 決定: 與其不斷在 Git 上打補丁, 不如從頭設計一個真正符合現代工作流的版本控制系統。
這不是為了取代 Git 成為「標準」, 而是為追求極致效率的個人開發者提供更好的選擇。
核心理念轉變
Jujutsu 不是在 Git 上加工具, 而是重新思考版本控制該是什麼樣子 :
Change-based, 而非 Commit-based
每個修改都是一個獨立的 “change”
Change 可以隨時修改, 不需要 amend 或 rebase
Working Copy 即 Commit
你的工作目錄就是一個 commit
不需要 git add + git commit 兩階段
真正的非線性歷史
不需要 branch 也能管理多條開發線
衝突作為一等公民存在於歷史中
實際操作對比
場景一:修改歷史 Commit
Git 方式:
git rebase -i HEAD~3
# 標記要修改的 commit 為 'edit'
# 進行修改
git add .
git commit --amend
git rebase --continue
git-revise 方式:
# 進行修改
vim some_file.py
# Stage 修改
git add some_file.py
# 應用到目標 commit
git revise # 直接更新該 commit
Jujutsu 方式:
jj edit # 直接切換到該 change
# 進行修改
jj commit -m "updated" # 自動更新該 change
場景二:管理多個功能開發
傳統 Git 方式:
git checkout -b feature-A
# 開發 feature-A
git commit -m "A"
git checkout -b feature-B
# 開發 feature-B
git commit -m "B"
# 要修改 A 時
git checkout feature-A
# 修改
git commit --amend
git checkout feature-B
git rebase feature-A # 手動 rebase
git-branchstack 方式:
# 所有工作在本地分支進行
git commit -m "[feature-A] Implement A"
git commit -m "[feature-B:feature-A] Implement B"
# 生成分支
git branchstack
# 要修改 A 時
git add modified_files
git revise # 修改 A 的 commit
# 重新生成分支, 自動處理依賴
git branchstack
Jujutsu 方式:
# 不需要建立 branch
jj new -m "feature A" # 創建新 change
# 開發 feature A
jj new -m "feature B" # 基於當前創建新 change
# 開發 feature B
# 要修改 A 時
jj edit
# 修改完自動處理依賴
Jujutsu 的核心特性
1. 自動追蹤所有歷史
jj op log # 查看所有操作歷史
jj op undo # 撤銷任何操作
jj op restore # 恢復到任何時間點
不需要 git reflog, 所有操作都可追溯和回復。
2. 衝突處理的新思路
# Jujutsu 讓你可以 commit 帶有衝突的狀態
jj new # 即使有衝突也能繼續開發
jj resolve # 稍後解決衝突
3. 與 Git 無縫協作
# Jujutsu 可以操作 Git repo
jj git clone
jj git push
jj git fetch
# 現有 Git repo 也能用 jj
cd my-git-repo
jj init --git-repo .
為什麼 Jujutsu 是個人效率工具的終極形態?
心智模型更簡單
Git : Branch → Stage → Commit → Push → Rebase → Merge
Jujutsu : Change → Edit → Evolve
對於個人開發者來說, 這意味著更少的認知負擔, 更多的時間專注在實際問題上。
更安全的實驗
所有操作都可以輕鬆撤銷
不需要擔心「搞壞」歷史
鼓勵更頻繁的實驗和重構
更適合現代個人工作流
Code Review 驅動的開發
頻繁的 Commit 修改
多個 PR 同時進行
不需要團隊統一工具 (可以單人使用 jj, 推送時轉為 Git)
實戰案例:用 Jujutsu 管理 Feature Stack
# 初始化
jj git clone https://github.com/user/repo.git
cd repo
# 創建第一個功能
jj new -m "Add user authentication"
# 開發...
jj describe -m "Add login form and validation"
# 基於此創建第二個功能
jj new -m "Add user profile page"
# 開發...
# 創建第三個功能
jj new -m "Add profile editing"
# 開發...
# 查看當前狀態
jj log
# 發現第一個功能需要修改
jj edit
# 修改...
jj describe -m "Updated authentication logic"
# 自動處理後續依賴, 不需要手動 rebase!
# 推送到 GitHub
jj git push --change # 為每個 change 推送對應分支
學習曲線
現有 Git 用戶 : 可以繼續在 Git repo 中使用 jj, 逐步適應
新專案 : 直接用 jj git init 開始, 享受完整體驗
團隊協作 : 個人可以用 jj 提升效率, 推送時轉換為 Git, 不影響團隊其他成員
這是一個個人選擇 , 不需要說服整個團隊改變工作流程。
結語:效率工具的個人化旅程
從 git-revise 到 git-branchstack, 再到 Jujutsu, 這是一段持續追求更高效率的旅程。每個工具都代表了開發者對「版本控制應該如何輔助我的工作」的不同思考。
這些工具的共同點是:
它們都是個人效率工具 , 不需要整個團隊採用
它們都在挑戰 Git 的既有模式
它們都專注於減少摩擦, 讓開發者更專注於解決問題
Jujutsu 的特別之處在於, 它不只是改善 Git 的某個面向, 而是重新思考了整個版本控制的心智模型。對於願意投資學習新工具來提升長期效率的開發者來說, 它可能是最佳選擇。
最重要的是: 這是一個個人選擇 。你不需要等待團隊共識, 不需要說服所有人。如果 Git 的複雜性讓你感到疲憊, 如果你想要更流暢的開發體驗, 那就試試這些工具吧。
或許你會發現, 提升效率的關鍵不是更努力地使用現有工具, 而是找到更適合你的工具。
延伸資源
試試看,你可能再也回不去 Git 了! 🚀
版本控制的「柔術」🥋
AI 生成聲明: 本文初稿由 Gemini AI 2.5 Flash 模型 生成, 再由個人手動修改而成。
從 Git 修訂工具到 Jujutsu 的優雅進化
許多資深開發者都對 Git 的強大功能愛恨交織。它強大, 但某些操作(特別是修改歷史和管理一系列依賴的變更時)卻異常複雜, 像是 git rebase -i 這樣的指令既是利器, 也常是困擾的源頭。
我們將探討一種更優雅、更直覺的版本控制解決方案:Jujutsu (jj) 。它並不是要取代 Git, 而是作為一個建立在 Git 基礎上的現代化前端, 帶來革命性的工作流程。
第一階段:Git 生態系統的修補與嘗試
在 Jujutsu 誕生之前, 許多工具試圖修補 Git 的「歷史修改」痛點。這些嘗試為 jj 的核心設計奠定了基礎。
痛點一:修訂歷史的麻煩 - git-revise 的出現
問題: 在 Git 中修改一個比較舊的 commit, 你需要用 git rebase -i, 找到那一行, 將 pick 改成 edit, 修改後再 git commit --amend, 最後 git rebase --continue。過程繁瑣且容易出錯。
解決方案的萌芽: 像 git-revise 這樣的工具, 讓修訂一個舊 commit 變得更簡單, 通常只需一個指令, 就能自動處理中斷和繼續的步驟。它證明了「歷史修訂可以更簡單 」的可能性。
痛點二:依賴變更的管理 - git-branchstack 的概念
問題: 當你在一個功能上提交了多個依賴的 commits, 如果底層重構的 commit 需要修改, 後續所有 commits 都需要手動 rebase, 或者面對重複的衝突解決。
解決方案的探索: git-branchstack 等工具, 嘗試建立一個「堆疊式分支」的概念, 讓開發者能更清楚地追蹤和操作一系列相互依賴的變更。這突顯了開發者對「自動化處理變基 」的渴望。
第二階段:Jujutsu 的誕生與核心概念
Jujutsu 正是吸收了這些工具的經驗和願景, 將其融入一個全新的版本控制系統介面中。它重新定義了幾個核心概念:
核心概念一:工作區即提交 (Working Copy is a Commit)
告別暫存區 (Staging Area): 在 jj 中, 你的工作目錄狀態永遠 是一個提交(commit)。你對檔案的修改會自動被視為對當前工作提交的修改。
好處: 不再需要 git add, 也沒有 git stash 的概念。
核心概念二:不變的「變更 ID」 (Change ID)
Git 的問題: 在 Git 中, 你修改一個舊提交(例如使用 amend 或 rebase)會產生一個全新的 Commit ID (SHA-1 hash)。
Jujutsu 的解決: jj 為每個邏輯變更(Change)分配一個不變的 Change ID 。當你修訂一個 commit 時, 它的 Commit ID 會改變, 但 Change ID 保持不變。
好處: 讓 jj 能夠在底層追蹤變更的演進, 即使歷史被重寫, 邏輯變更仍可追溯。
核心概念三:自動、安全且強大的變基 (Automatic Rebasing)
終結 rebase 的恐懼: 這是 jj 的殺手鐧。當你修改歷史中的某個提交時, 所有後續依賴於它的提交會自動且安全地 進行變基。
例如: 你使用 jj edit <old-commit-id> 修改了一個底層提交, 你後續的 commits 會像「柔術」一般優雅地、自動地移到新修訂的提交之上。
第三階段:Jujutsu 帶來的工作流程變革
jj 的指令設計更直覺、更以「變更」為中心, 極大地簡化了日常操作。
jj 操作
傳統 Git 工作流
優勢與變革
jj undo
難以實現, 需要 git reflog
一鍵撤銷 :所有操作(包括變基、修訂)都是可撤銷的, 提供了無損的工作安全網 。
jj squash
git rebase -i 或 git commit --amend
輕鬆合併: 快速將當前工作區的變更併入父提交。
jj split
git rebase -i + 手動操作
輕鬆拆分: 在不修改原提交的前提下, 將其部分內容拆分為新提交。
jj log
git log --graph
清晰日誌: 預設輸出更易讀的變更圖, 並顯示 Change ID。
結語:版本控制的未來已來
Jujutsu 將版本控制的複雜性抽象化, 提供了更直覺、更安全、更符合人腦思考邏輯的操作介面。它將我們從 git-revise 和 git-branchstack 試圖解決的局部痛點中解放出來, 提供了一個更全面、優雅的解決方案。
如果你厭倦了 Git 繁瑣的歷史修改流程, 渴望更流暢、更少出錯的開發體驗, 那麼是時候擁抱這門版本控制的「柔術」了。
建置 Jupyter Notebook 的 Rust 運作環境
最近重新安裝了 macOS Big Sur,想試試 Jupyter Notebook 的 Rust 環境,再加上這幾天放假比較有時間,就把安裝的過程記錄下來。
安裝 Miniconda
過去一直覺得 Anaconda 有點肥大,所以這次決定先從安裝比較精簡的 miniconda 開始:
$ brew install --cask miniconda
新增 conda-forge channel 以便安裝需要的套件如 jupyterlab:
$ conda config --add channels conda-forge
$ conda config --set channel_priority strict
然後需要初始化 conda 的 base 環境,一般都是跑 conda init,但它會加一段不是很通用的設定到我個人的 .zshrc,我不是很喜歡這種做法,所以就先只套用在目前的 shell 裡:
$ eval `conda shell.zsh hook`
創建新的 conda 環境
創建一個新的環境叫 rust-notebook:
(base) $ conda create -n rust-notebook python=3
(base) $ conda activate rust-notebook
安裝 JupyterLab
在新的環境指定安裝 jupyterlab 版本 2.2.9,因為最新的 3.0 似乎與最新的 jupyterlab-plotly 不相容:
(rust-notebook) $ conda install jupyterlab=2.2.9
然後安裝 jupyterlab-plotly:
(rust-notebook) $ jupyter labextension install jupyterlab-plotly
安裝 evcxr_jupyter
假設 Rust 已經安裝完成,直接用 Cargo 安裝 Rust 的 Jupyter kernel:
$ cargo install evcxr_jupyter
$ evcxr_jupyter --install
啟動 JupyterLab:
(rust-notebook) $ jupyter lab
如果可以看到下列 Rust 圖示應該就是成功了:
範例執行結果
試一下:
println!("Hello, Jupyter!");
Hello, Jupyter!
來畫個圖:
:dep plotters = { git = "https://github.com/38/plotters", default_features = false, features = ["evcxr", "line_series"] }
extern crate plotters;
use plotters::prelude::*;
use plotters::series::*;
let figure = evcxr_figure((640, 480), |root| {
root.fill(&WHITE);
let mut chart = ChartBuilder::on(&root)
.caption("y=x^2", ("Arial", 50).into_font())
.margin(5)
.x_label_area_size(30)
.y_label_area_size(30)
.build_ranged(-1f32..1f32, -0.1f32..1f32)?;
chart.configure_mesh().draw()?;
chart.draw_series(LineSeries::new(
(-50..=50).map(|x| x as f32 / 50.0).map(|x| (x, x * x)),
&RED,
)).unwrap()
.label("y = x^2")
.legend(|(x,y)| PathElement::new(vec![(x,y), (x + 20,y)], &RED));
chart.configure_series_labels()
.background_style(&WHITE.mix(0.8))
.border_style(&BLACK)
.draw()?;
Ok(())
});
figure
y=x^2
0.0
0.2
0.4
0.6
0.8
-0.8
-0.6
-0.4
-0.2
0.0
0.2
0.4
0.6
0.8
1.0
y = x^2
參考