Getting started with jj

Ellie Huxtable

jj 入門

原文由 Ellie Huxtable 發布,訂閱此部落格

過去幾週我一直在用 jj!這不是我第一次嘗試它,但卻是第一次真正上手並持續使用。

多年來,我的 git 工作流程都是「改完東西,然後 git commit --amend --no-edit && git push --force-with-lease」,而且在同一個分支上。這讓我的修改能以非常低的延遲保持在遠端的最新狀態。PR 通常只有少數幾個 commit,通常只有一個,我也會盡量讓它們保持精簡。

自從開始跟 agent 一起工作後,我發現自己切換分支的頻率變高了很多。因此,我要嘛得用 git stash,要嘛得隨便弄個有點蠢的 wip commit,才能避免不同修改互相干擾。

有請我們的新英雄,jj!這裡的模型有點不一樣。我不會寫什麼長篇大論的手冊,因為網路上已經有很多了,而且都比我隨便塞進筆記裡的東西好得多。

簡單來說,最吸引我的地方在於,我的修改永遠都是已提交的狀態。每一次編輯都會自動 amend 到最新的 commit,而 push 就會覆蓋遠端(或者用 jj 的說法,就是把它「橫向移動」)。

編輯一個 change 非常輕鬆,不需要搞那套 checkout / rebase 的繁瑣流程。感覺就像有人把我最喜歡的 git 工作流程直接做成了一個工具。我也不太明白自己為什麼花了這麼久才搞懂這件事。

這篇真的就只是隨手把腦中的想法倒出來而已。之後學到更多東西,應該還會再發一些筆記。

工作流程

要進行一項修改時,我的工作流程是:

jj new main

<do some coding>

jj describe -m 'feat: something really cool'
jj git push -c @

這樣就完成了。合併 PR,然後重複。

在 jj 裡,我們談的是 change 而不是 commit。一個 change 就是一個不斷演進的 commit。而「@」指的就是當前的 change

開始一個新的 change

在開始工作之前,你應該先建立一個 change。接下來你做的所有編輯都會放在這裡

jj new main

這會在 main(也就是帶有 main 書籤的那個 commit)之上建立你的 commit(剛開始接觸時,change 跟 commit 的差別真的很讓人困惑)。如果你想建立一個以當前 change 為父節點的新 change,只要執行 jj new 就好。

為 change 加上說明

你可能已經習慣先把一些修改加到 staging area,再用一段訊息把它們 commit 起來。不過在 jj 裡,你的修改已經自動被加入了。但你的 change 可能還沒有 description!(就像 commit message 一樣)

jj describe -m 'hello i am a message'

你也可以在建立 change 的當下就幫它加上說明:

jj new -m "hello i am a message"

把 commit 推送到新分支

如果你正在某個 change 上,對它很滿意,想把它推到 GitHub 上讓某個 agent 來吐槽你(Claude 寫)的程式碼呢?

很簡單。

jj git push -c @

也就是「用 git 來推送當前的 commit」。它會自動建立一個分支並推送到遠端。你其實可以在修改過程中一再執行這個指令,它會自動把 jj 的魔法轉譯成 git 的 amend 和 force push。

不過我還是很期待 jj 能擁有自己的協定和託管平台。

編輯 commit

如果想跳回去編輯某個已有的 change?很簡單

jj edit <change-id>

對我來說,從這裡開始就真的感覺到它的強大,同時也是我原本想套用的心智模型開始瓦解的地方。不用再去瞎搞什麼 checkout、rebase 之類的東西。

jj 同時有 change 和 commit。如果回想一下,它是不斷演進一個 commit,而不是有個 staging area,那麼我們可以把 change 想成是穩定的 ID,而 commit ID 則是每次編輯都會跟著變的那個

復原操作

在 jj 裡你做的幾乎任何事都會被記錄在 op log 裡。如果做了什麼結果搞砸了?jj undo 來救你。

更多 git 相關操作

jj 目前在很大程度上還是寄生在 git 之上。他們已經讓轉換現有 repo 變得很簡單,也能輕鬆跟 GitHub 整合

# Create a jj repo inside of a git repo
jj git init

# Fetch from the remote (github etc)
jj git fetch

# Push
jj git push

# Clone
jj git clone

好,那分支在哪裡

沒有分支!至少不是你習慣的那種。jj 用的是「書籤(bookmark)」,也就是你可以附加到某個 commit 上的字串。當你推送一個 change 時,它會自動幫你建立一個書籤——例如 push-refrefref

# bookmark the current change with a name
jj bookmark create <name>

# move a bookmark to a new commit
jj bookmark set <name> -r <commit>

# other things exist just use --help

我目前最感到困擾的是,建立新 change 時書籤並不會跟著移動。

節錄自詞彙表:

跟 Git 不同,jj 沒有「當前書籤」的概念;當你建立新的 commit 時,書籤不會跟著移動。如果 commit 被重寫,書籤才會自動跟著它移動。

之後我會再另外寫一篇關於 rebase、編輯和其他有趣玩法的東西


註:用 Vim 寫這篇超級困擾,因為我把 jj 綁定成 <esc> 了。

本文章由 muse-spark-1.2-contributor 進行翻譯

留言