Getting started with jj

Ellie Huxtable

jj 入門

原文は Ellie Huxtable により に公開されました。 このブログを購読する

ここ数週間、jj を使っている。試すのは初めてではないが、定着したのは今回が初めてだ。

何年もの間、僕の git ワークフローは、ブランチの上で「変更を加えたら git commit --amend --no-edit && git push --force-with-lease する」というものだった。そうすることで、変更をほぼ遅延なくリモートに反映できていた。PR はコミット数が少ないことがほとんどで、たいていは 1 つ。できるだけ小さく保つようにしていた。

エージェントと一緒に作業するようになってから、ブランチを切り替える頻度がぐっと増えた。そのせいで、git stash するか、変更同士が干渉しないように適当な wip コミットを作るかのどちらかを強いられていた。

そこで登場するのが、我らが新たなヒーロー jj だ!こちらのモデルは少し違う。巨大なマニュアルを書くつもりはない。世の中にたくさんあるし、僕が思いつきで殴り書きするメモよりよっぽど出来がいいからだ。

とりあえず言えるのは、一番気に入っているのは変更が常にコミットされていることだ。編集するたびに最新のコミットが自動的に amend され、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 では commit よりも change という言葉を使う。change とは、常に進化し続けるコミットのようなものだ。そして「@」は現在の change を指す。

新しい change を始める

作業を始める前に、change を開始しよう。これから行う編集はすべてここに収まる。

jj new main

これは main(bookmark が main のコミット)の上にあなたのコミット(初心者のうちは change と commit の違いはややこしく感じるだろう)を作成する。現在の change の子として新しい change を作りたいなら、単に jj new を実行すればいい。

change に説明を付ける

おそらく、変更をステージングエリアに追加してからメッセージを付けてコミットする、という流れに慣れているだろう。jj では、変更はすでに追加されている。ただ、change にはまだ description(コミットメッセージのようなもの)が付いていないはずだ!

jj describe -m 'hello i am a message'

change を作るのと同時に説明を付けることもできる。

jj new -m "hello i am a message"

コミットを新しいブランチにプッシュする

change の上で作業していて、出来に満足したので GitHub に上げてエージェントに(Claude の)コードをこき下ろさせたいときは?

簡単だ。

jj git push -c @

要するに「git を使って現在のコミットを push する」ということだ。自動でブランチが作成され、リモートに push される。変更を加えながら何度でもこれを実行でき、jj の魔法が自動的に git の amend と force push に変換される。

とはいえ、jj が独自のプロトコルとホストを持つようになるのが楽しみだ。

コミットを編集する

既存の change に戻って編集したいときは?簡単だ。

jj edit <change-id>

このあたりから jj の強力さが実感できてくるところだし、同時に、既存のメンタルモデルに無理やり当てはめようとすると破綻し始めるところでもある。checkout だの rebase だの、そういった面倒なことをごちゃごちゃやる必要がないのだ。

jj には change と commit の両方がある。ステージングエリアを持つ代わりにコミットを常時進化させるのだと考えれば、change は安定した ID で、commit ID は編集のたびに変わるものだと捉えることができる。

元に戻す

jj で行った操作はほぼすべて op ログに保存される。何かやって失敗したとしても? jj undo が助けてくれる。

その他の git 関連

jj は今のところ、ほとんど git の上に乗っかって動いている。既存のリポジトリを変換するのも、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」を使う。これはコミットに紐付けられる文字列だ。change を push すると、自動的に bookmark が作成される。例えば 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 を作っても bookmark が移動しないことだ。

用語集からの引用。

Git とは異なり、「現在の bookmark」という概念はない。新しいコミットを作成しても bookmark は移動しない。コミットが書き換えられた場合は、bookmark は自動的にそのコミットに追従する。

リベースや編集、その他楽しいことについては、また別の機会に書くつもりだ。


余談:これを Vim で書くのはめちゃくちゃ面倒だった。jj<esc> に割り当てているからだ。

この記事は「muse-spark-1.2-contributor」を使用して翻訳されました。

コメント