🥋

Git互換 Jujutsu (jj) バージョン管理システムのメリットと基本的な使い方

に公開

Jujutsu(通称 jj)は Google で開発された Git 互換のバージョン管理システムです。Git リポジトリでそのまま使えます。

すべての変更が自動で記録され、並行作業が簡単にできる設計なので、AI にコードを生成させて比較したり、試行錯誤を繰り返す現代の開発スタイルと相性が良いです。

1. jj の特徴

Jujutsu

1. すべてが自動で記録される
jj では作業中の状態も含めてすべてが「コミット」として管理されます。jj ではこれを「change」と呼びます。ファイルを保存すれば即座に記録されるので、git addgit stash もいりません。「コミットし忘れて変更が消えた」が起きません。

2. 並行作業がしやすい
複数の機能を同時に開発していても混乱しにくい設計です。jj new で分岐して jj edit で戻るだけ。

3. Git と併存できる
jj は Git リポジトリの上で動くので、チームが Git を使っていても自分だけ jj に移行できます。うまくいかなければいつでも Git に戻れるので、リスクなく試せます。

4. リモートに push される履歴がキレイ
Git/GitHub では、ローカルで作ったコミットがそのままリモートに全部上がります。fix typoWIP といったコミットも残ります。

jj は違います。ローカルでは試行錯誤の履歴が残りますが、リモートには最終的な変更だけを push します。

【GitHub の場合】
ローカル:commit1 → commit2 → commit3 (fix typo) → commit4
リモート:全部そのまま上がる

【jj の場合】
ローカル:change を何度も更新(履歴は残る)
リモート:最終的な 1 change だけ

これは Google の Gerrit というコードレビューシステムの「1変更1コミット」という思想を引き継いでいます。

2. インストール

# macOS
brew install jj

# Windows
winget install jj-vcs.jj

# cargo 経由(全プラットフォーム共通)
cargo install --locked jj-cli

初回はユーザー情報の設定も必要です。

jj config set --user user.name "Your Name"
jj config set --user user.email "your@email.com"

3. 基本的な使い方

3.1 リポジトリの準備

新しくクローンする場合:

jj git clone <url>

既存の Git リポジトリを使う場合:

jj git init

これで .git.jj が両方存在する状態(colocate モード)になり、git コマンドも jj コマンドも両方使えます。IDE の Git 連携もそのまま動きます。

3.2 作業開始

jj new main -m "機能Aの実装"

jj new main で main から分岐して新しい作業を始めます。

jj new だけだと今いる場所から分岐します。jj new main と明示すると、今どこにいても main から始められるので、並行開発のときに便利です。

# 機能Aの作業中に、別の機能Bを始めたくなった
jj new main -m "機能Bの実装"    # main から新しく分岐

# 機能Aに戻りたいときは jj log で change ID を確認して
jj edit <changeID>
# または説明文で検索
jj log | grep "機能A"

3.3 作業中

ファイルを編集するだけ。保存すれば自動的に記録されます。

jj status   # 状態確認
jj log      # 履歴確認
jj desc -m "説明を更新"  # メッセージ変更

3.4 完了したら push

jj bookmark create feature-a   # push 直前に bookmark を作成
jj bookmark track feature-a    # リモートで tracking
jj git push

bookmark は GitHub の branch 名になります。新しい bookmark は track でリモートに紐づけてから push します。push 直前に作ると、不要な bookmark が残りません。

4. 覚えておくこと

4.1 ログと状態確認

jj(または jj log)
change のツリー(履歴)が見れます。jj だけで OK です(デフォルトコマンドが jj log)。-n で表示件数を絞れます。

@  abc123 "機能Aの実装"

○  main

@ マークがついてるのが今いる場所(現在の change)です。作業を始めるときは jj new main のように起点を明示すると、どこから始めてるか明確になって安全です。

jj status
今いる change の状態が見れます。変更されたファイル一覧など。Git の git status に近いです。

jj op log
jj の「操作」の履歴です。describe した、new した、push した、などの操作が記録されています。履歴が長くなってきたら -n で件数を絞れます。

jj op log -n 10   # 直近10件だけ表示

jj op undo / jj op restore
間違えたときはここから戻せます。

jj op undo     # 直前の操作を取り消す
jj op restore <操作ID>  # 特定の時点に戻す

restore や undo 自体も操作として記録されるので、「戻したけどやっぱり違った」というときも大丈夫です。

jj op log
# @  abc123  op restore ...    ← 今ここ(さっき restore した)
# ○  def456  describe ...
# ○  ghi789  new ...           ← 本当はここに戻りたかった

jj op restore ghi789   # さらに別の時点に移動できる
jj op undo             # または直前の restore を取り消す

4.2 commit と describe

  • jj desc → 説明を変更するだけ
  • jj commit → 説明を変更して、次の change へ移動

jj commit -m "メッセージ"jj desc -m "メッセージ" してから jj new するのと同じです。今の作業に区切りをつけて次に進みたいときに使います。

jj desc は何回実行しても、同じ change の説明が上書きされるだけです。Git のようにコミットが増えていくことはありません。これが「1変更1コミット」の思想です。

4.3 bookmark

bookmark は GitHub に push するときに branch 名になるラベルです。

bookmark は自動で進まない

Git と jj で動きが違います。

【Git の場合】
main ← branch はここ
↓ git commit すると...
main ← 自動的に進む

【jj の場合】
○ main ← bookmark はここのまま動かない

@ 作業中の change

jj では change を作っても bookmark は元の場所のまま動きません。push する前に自分で移動させます。

  • 既存の bookmark を移動: jj bookmark set main
  • 新しい bookmark を作成: jj bookmark create feature-a(今いる場所に作られる)

tracking について

bookmark を push するには、リモートとの紐づけ(tracking)が必要です。

既存の bookmark(main など)
jj git clone で作ったリポジトリでは main は最初から tracking されています。jj git init で既存リポジトリを jj 化した場合は手動で設定が必要です。

jj bookmark track main@origin   # main を tracking 対象に追加

新しく作った bookmark
jj bookmark create で作った bookmark は tracking されていないので、push 前に設定します。

jj bookmark create feature-a
jj bookmark track feature-a     # リモートで tracking
jj git push

tracking している bookmark は jj git fetch で自動的に更新されます。

jj bookmark list --all          # tracking 状態を確認

4.4 Git コマンドとの対応

そのまま使える

gitjjjj git に置き換えるだけ。

Git jj
git clone jj git clone
git init jj git init
git fetch jj git fetch
git push jj git push
git status jj status
git log jj log(jj だけでも可)
git diff jj diff

jj では不要

Git jj
git add 不要(自動で記録される)
git stash 不要(変更は自動保存されるので、別の change に移動しても消えない)

考え方が違う

Git jj 備考
git commit jj commit 次の change へ移動
git commit --amend jj desc 編集するだけでも可
git branch jj bookmark create bookmark は自動で進まない
git checkout -b jj new + bookmark
git switch jj edit change を指定
git reset jj op undo 何でも戻せる
git reflog jj op log 操作履歴を表示

jj 独自

jj 説明
jj op restore 特定の操作時点に復元
jj abandon 今の change を破棄(親に戻るには jj edit も必要)

4.5 長い作業の進め方

機能開発が長くなってきたとき、履歴をどう管理するかは2つのアプローチがあります。

方法1: desc を繰り返す(1 change で作業)

# 作業中、何度でも説明を更新
jj desc -m "機能A: 基本実装"
# ... 作業 ...
jj desc -m "機能A: バリデーション追加"
# ... 作業 ...
jj desc -m "機能A: エラーハンドリング完了"

change は1つのまま、説明だけが更新されます。試行錯誤の履歴は jj op log に残っているので、いつでも戻れます。jj の「1変更1コミット」思想に忠実なやり方です。

方法2: commit で区切り → 後で squash

jj commit -m "機能A: 基本実装"
# ... 作業 ...
jj commit -m "機能A: バリデーション追加"
# ... 作業 ...
jj desc -m "機能A: エラーハンドリング完了"

# push 前にまとめる
jj squash --from <最初のchangeのID>

作業の区切りが jj log で見えるので、段階的に進捗を確認しやすくなります。push 前に squash で1つにまとめれば、リモートには1つの change として上がります。

使い分けの目安

状況 おすすめ
小〜中規模の変更 desc を繰り返す
大規模で段階的に確認したい commitsquash
途中でレビューをもらいたい commit で分ける
AI に段階的に生成させて比較 commit で分けると差分が見やすい

どちらも最終的にリモートに push される形は同じなので、作業中の見通しの良さで選んでください。

まとめ

jj は Git と併存できるので、リスクなく試せます。

  • 自動保存: git addgit stash が不要。ファイルを保存すれば記録される
  • 安全な試行錯誤: jj op undo で何でも戻せる。操作履歴は消えない
  • 並行作業が楽: jj new main で分岐、jj edit で移動するだけ
  • 履歴がキレイ: ローカルの試行錯誤はリモートに残らない

既存の Git リポジトリで jj git init するだけで始められます。合わなければ .jj フォルダを消すだけで元に戻れます。

5. 参考文献

公式

解説記事

Discussion