Git互換 Jujutsu (jj) バージョン管理システムのメリットと基本的な使い方
Jujutsu(通称 jj)は Google で開発された Git 互換のバージョン管理システムです。Git リポジトリでそのまま使えます。
すべての変更が自動で記録され、並行作業が簡単にできる設計なので、AI にコードを生成させて比較したり、試行錯誤を繰り返す現代の開発スタイルと相性が良いです。
1. jj の特徴

1. すべてが自動で記録される
jj では作業中の状態も含めてすべてが「コミット」として管理されます。jj ではこれを「change」と呼びます。ファイルを保存すれば即座に記録されるので、git add も git stash もいりません。「コミットし忘れて変更が消えた」が起きません。
2. 並行作業がしやすい
複数の機能を同時に開発していても混乱しにくい設計です。jj new で分岐して jj edit で戻るだけ。
3. Git と併存できる
jj は Git リポジトリの上で動くので、チームが Git を使っていても自分だけ jj に移行できます。うまくいかなければいつでも Git に戻れるので、リスクなく試せます。
4. リモートに push される履歴がキレイ
Git/GitHub では、ローカルで作ったコミットがそのままリモートに全部上がります。fix typo や WIP といったコミットも残ります。
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 コマンドとの対応
そのまま使える
git を jj や jj 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 を繰り返す |
| 大規模で段階的に確認したい |
commit → squash
|
| 途中でレビューをもらいたい |
commit で分ける |
| AI に段階的に生成させて比較 |
commit で分けると差分が見やすい |
どちらも最終的にリモートに push される形は同じなので、作業中の見通しの良さで選んでください。
まとめ
jj は Git と併存できるので、リスクなく試せます。
-
自動保存:
git addやgit stashが不要。ファイルを保存すれば記録される -
安全な試行錯誤:
jj op undoで何でも戻せる。操作履歴は消えない -
並行作業が楽:
jj new mainで分岐、jj editで移動するだけ - 履歴がキレイ: ローカルの試行錯誤はリモートに残らない
既存の Git リポジトリで jj git init するだけで始められます。合わなければ .jj フォルダを消すだけで元に戻れます。
5. 参考文献
公式
解説記事
Discussion