Jujutsu(ジュジュツ、コマンド名は jj)は、Gitのリポジトリをそのまま読み書きできるバージョン管理システムです。作業中のファイルが常に1つのコミットとして記録されるため git add もstashも要らず、手元の操作は jj undo で戻せます(pushでリモートへ送った内容までは戻りません)。2026年9月時点の最新版は0.45.1で、1.0前のため、月1回のリリースで破壊的変更が入ることがあります。この記事では0.45.1を実際に動かし、Windows・Mac・Linuxのインストールから、既存のGitリポジトリで1つの変更をGitHubへpushするまで、そしてネットの古い解説が動かない理由までを確認した結果をまとめます。
まとめ:Jujutsu(jj)の要点(v0.45.1時点)
- 何者か:Martin von Zweigbergk氏が2019年に趣味で始め、現在はGoogleで本人の専任プロジェクトになっているGit互換VCS。ただしGoogleの公式サポート製品ではない。ライセンスはApache-2.0。
- インストール:Windowsは
winget install jj-vcs.jj、macOSはbrew install jj、Arch Linuxはpacman -S jujutsu、どのOSでもcargo install --locked --bin jj jj-cli。 - Gitとの違い:作業コピー自体がコミット(
@)で、ステージングが無い。ブランチの代わりのブックマークは自動で進まない。 - 始め方:既存のGitリポジトリで
jj git initを打つだけ。0.34以降は.gitと同居する「colocate」が既定で、Gitコマンドも並行して使える。 - 注意:
jj git push --allow-newは0.42で削除、jj rebase -dは0.36で-oに改名。2025年以前の解説はそのまま動かないことが多い。submodule・Git LFS・Gitフックは非対応。
以下、インストール、Gitとの違い、日々の使い方、コンフリクトとundo、版差、採用を見送るべき条件の順に説明します。
Jujutsu(jj)の開発元と安定度
公式リポジトリは github.com/jj-vcs/jj です(2024年に個人アカウントの martinvonz/jj から移転)。READMEの「Mandatory Google Disclaimer」では、作者が2019年末に趣味で始め、現在はGoogleで本人の専任プロジェクトになっており、複数のGoogle社員が開発に加わっていると説明しています。同じ箇所に「Googleのサポート対象製品ではない」とも明記されており、サポートはコミュニティが担います。
安定度について、READMEは「実験的なバージョン管理システム」と位置付けています。Git互換の部分は安定していて、コア開発者は全員 jj で jj 自体を開発しています。一方で、1.0.0までにワークフローの変更やディスク上の形式の後方互換を破る変更が入ると予告しています。リリースは毎月第1水曜日前後に出ており、2026年は0.37.0(1月7日)から0.45.0(9月2日)まで毎月1本です。
Jujutsuのインストール手順:OS別のコマンドと初期設定
公式の手順書(install-and-setup)に載っている方法だけを挙げます。cargoでビルドする場合はRust 1.89以上が必要です(v0.45.1のCargo.tomlの rust-version が1.89。手順書の本文は1.88のまま)。どの方法で入れても実行時にGit 2.41.0以上が要るため、Ubuntu 22.04やDebian 11の標準のGitでは先にGitを更新します。
Windows:wingetかscoop
Windowsはパッケージマネージャー2種が公式手順に載っています。どちらも最新リリースが入ります。
winget install jj-vcs.jj
# または
scoop install main/jj
WSL上で使う場合はWSL側でLinuxの手順により別途入れます。設定ファイルもWindows側とは別になります(場所は後述のよくある質問を参照)。
macOS:Homebrew
brew install jj
jj --version
Homebrewの jj formulaは2026年9月28日時点で0.45.1(公式リリースと同じ)です。MacPortsなら sudo port install jujutsu です。
Linux:pacman・cargo-binstall・cargo
# Arch Linux
sudo pacman -S jujutsu
# ビルド済みバイナリを ~/.cargo/bin に置く(cargo-binstall導入済みの場合)
cargo binstall --strategies crate-meta-data jj-cli
# ソースからビルド(Ubuntu等は先に build-essential が必要)
cargo install --locked --bin jj jj-cli
Fedoraは公式手順にCOPRリポジトリ(aldantanneo/jj-vcs)経由の dnf install jj-cli が載っていますが、公式パッケージではありません。Ubuntu・Debianの公式リポジトリ向けの手順は無いため、cargoを使わないならGitHubリリースのビルド済みバイナリ(jj-v0.45.1-x86_64-unknown-linux-musl.tar.gz 等)を展開してPATHに置くのが手早い方法です。
初期設定:名前とメールアドレス
コミットの作成者情報はGitの設定を読みません。最初に次の2行を実行します。
jj config set --user user.name "Taro Yamada"
jj config set --user user.email "[email protected]"
jj config path --user # 書き込まれたファイルの場所を確認
0.45.0から、ユーザー設定ファイルが複数あるときの --user の書き込み先が変わりました。以前は対話的に選ばせていましたが、現在は最初に読み込まれるファイル(旧来の ~/.jjconfig.toml があればそれ、無ければ ~/.config/jj/config.toml または conf.d/ の先頭ファイル)へ黙って書き込みます。書き込み先を指定したいときは --file <PATH> を付けます。
Gitとの違い:作業コピーがコミットになる操作モデル
jj はGitのオブジェクト形式でデータを保存するので、リモートやCIから見れば普通のGitリポジトリです。変わるのは手元の操作モデルで、Gitに慣れた人がつまずくのはほぼ次の3点です。
ステージングが無く、作業コピーそのものがコミット
jj では作業中のファイル群が常に @(working-copy commit)というコミットになっています。jj コマンドを実行するたびにファイルの状態が自動でスナップショットされ、@ に取り込まれます。そのため git add に当たる操作が無く、stashも要りません。別の作業に移りたければ jj new で新しい空のコミットを作るだけで、それまでの変更は親コミットに残ります。逆に、コミットしたくないファイルは .gitignore に書いておかないと自動で取り込まれます。
change IDとcommit IDの2つのID
jj log の各行には2つのIDが出ます。先頭の英字(例 qrmzkurw)がchange IDで、コミットを書き換えても変わりません。後ろの16進(例 41a65610)がGitのcommit IDで、書き換えるたびに変わります。手元で動かしたとき、jj describe でメッセージを付けただけでcommit IDは 6226c719 から 41a65610 に変わり、change ID qrmzkurw はそのままでした。change IDは jj describe や jj rebase で書き換えても変わらないため、書き換え後も同じ変更を指し続けます。ただし jj squash で中身を全部移して空になった移動元のコミットは破棄され、そのchange IDは使えなくなります。
ブックマークとGitブランチの更新タイミングの違い
Gitのブランチに当たるものは、0.22で「bookmark」に改名されました。改名の理由は、Gitのブランチと挙動が違うため、とCHANGELOGに書かれています。一番の違いは、新しいコミットを作ってもブックマークが自動では付いてこない点です。pushする前に jj bookmark set <名前> -r @- のように位置を合わせる必要があります。ブックマークが無くても作業はでき、名前の無い変更をいくつも並行して持てます。ブランチの基本はブランチとは?バージョン管理で開発を分岐させる仕組みを参照してください。
GitとJujutsuのコマンド対応表
| やりたいこと | Git | jj(0.45.1) |
|---|---|---|
| 既存リポジトリで使い始める | – | jj git init |
| クローン | git clone URL |
jj git clone URL |
| 状態を見る | git status |
jj st |
| メッセージを付けて確定 | git commit -a -m |
jj commit -m |
| 直前のコミットに追加 | git commit --amend |
jj squash |
| メッセージだけ直す | git commit --amend -m |
jj describe -m |
| 作業を一時退避 | git stash |
jj new @- |
| 付け替え | git rebase |
jj rebase -o |
| cherry-pick | git cherry-pick |
jj duplicate -o |
| 変更を捨てる | git reset --hard |
jj abandon |
| 取得・送信 | git fetch / git push |
jj git fetch / jj git push |
| 操作の取り消し | git reflog+reset |
jj undo |
Gitコマンド側の詳しい意味はGitコマンド一覧にまとめています。
jjの基本的な使い方:既存リポジトリで1つの変更をpushするまで
既存のGitリポジトリへの導入
cd my-project # 既に .git があるリポジトリ
jj git init # .jj が作られ、.git と同居する
jj log
0.34以降は同居(colocate)が既定になったため、昔の解説にある --colocate は付けても付けなくても同じです。同居状態では git log や git diff もそのまま使えます。ただし git status は、jj の操作後は通常「Not currently on any branch.」(detached HEAD)と表示します。jj がHEADを @ の親に置くためで、故障ではありません。新規にクローンするなら jj git clone <URL> を使います。
jj log が全履歴を出さないのも仕様です。既定の表示範囲は present(@) | ancestors(immutable_heads().., 2) | trunk() で、今の作業コミット(@)、書き換え可能な(不変扱いでない)コミットとその近くの祖先、trunkだけを出します。作者で絞っているわけではありません。全部見たいときは jj log -r :: です。
変更の記録:describe・new・commit
echo "a" > a.txt
jj st # A a.txt が @ に取り込まれている
jj describe -m "add a" # @ にメッセージを付ける
jj new # 次の作業用に空のコミットを作る
# 上の2行は jj commit -m "add a" 1回と同じ結果になる
作業途中の変更を1つ前のコミットへ混ぜたいときは jj squash、1つのコミットを2つに分けたいときは jj split を使います。jj squash や jj describe でコミットを書き換えると、その子孫は自動で付け替えられます(手元で jj describe @- を実行したときも「Rebased 1 descendant commits.」と表示されました)。旧来の解説に出てくる jj amend と jj init は現行版にはありません。
GitHubへのpush:ブックマークの作り方で3通り
jj git remote add origin [email protected]:you/repo.git # clone した場合は不要
# 1) 名前を付けて push(-b を付けると追跡も自動で始まる)
jj bookmark create feature-a -r @-
jj git push -b feature-a
# 2) 名前を考えずに push(push-<change ID> という名前が自動で付く)
jj git push -c @-
# 3) 引数なしは、追跡中のブックマークのうち @ までの範囲にあるものを push
jj git push
ブックマークを作っただけで -b を付けずに jj git push すると、「Refusing to create new remote bookmark feature-a@origin」と出て何も送られません(終了コードは0なので、スクリプトでは気付きにくい点に注意)。以前はここで --allow-new を付けましたが、このフラグは0.36で非推奨、0.42で削除されました。毎回の追跡を省きたいなら、設定に [remotes.origin] と auto-track-bookmarks = "*" を書きます。
履歴を書き換えたあとのpushに --force は要りません。jj describe @- でpush済みのコミットを直したあと jj git push すると「move sideways」と表示されて更新されました。jj は最後にfetchしたリモートの状態と一致するときだけ上書きするので、動作は git push --force-with-lease 相当です。Git側での同じ操作はgit rebaseとは?使い方・mergeとの違いで解説しています。
コンフリクトの扱い:rebaseが途中で止まらない仕組み
Gitのrebaseはコンフリクトに当たるとその場で止まり、解消するか --abort するまで次に進めません。jj はコンフリクトをコミットの中身として記録し、rebase自体は最後まで完了させます。同じファイルの同じ行を別々に変えた2つのコミットで試すと、次のように表示されました。
$ jj rebase -s unuyrvux -o kvzrztkk
Rebased 2 commits to destination.
New conflicts appeared in 1 commits:
unuyrvux dd7fc53b (conflict) left
Hint: To resolve the conflicts, start by creating a commit on top of
the conflicted commit:
jj new unuyrvux
Then use `jj resolve`, or edit the conflict markers in the file directly.
jj log ではそのコミットに × と (conflict) が付き、ファイルには次の形のマーカーが書かれます。Gitの <<<<<<< と違い、片側を「差分」として示すので、どちらの変更を残すか判断しやすくなっています。
<<<<<<< conflict 1 of 1
+++++++ kvzrztkk 2f8b963e "right" (rebase destination)
right
%%%%%%% diff from: lromsktu 25c0f469 "base" (parents of rebased revision)
\\\\\\\ to: unuyrvux 000dec35 "left" (rebased revision)
-line1
+left
>>>>>>> conflict 1 of 1 ends
解消の手順はヒントのとおりで、jj new <衝突したコミット> で上に作業用コミットを作り、ファイルを直すか jj resolve でマージツールを開き、jj squash で解消結果を衝突したコミットへ戻します。解消するまで他の作業を続けても構いません。未解消のコミットは jj log -r 'conflicts()' で一覧できます。コンフリクト自体の仕組みはコンフリクトとは?Gitで変更が衝突する仕組みと解消手順で説明しています。
コンフリクトは標準のGitの形式では表せないため、jj はGitのコミット内に .jjconflict-base-* などの内部用ディレクトリとして保存します(公式のGit互換性資料による)。jj から操作する限り見えませんが、git switch で直接取り出すとこのディレクトリが作業コピーに現れます。pushしようとしてもWon't push commit … since it has conflictsと表示されて拒否されました(手元で確認)。「rebaseが常に成功する」は「解消しなくてよい」という意味ではありません。
操作ログとjj undo:0.33以降の連続取り消し
jj はリポジトリへの操作を1回ずつ操作ログ(operation log)に記録します。jj op log で一覧でき、各行に実行したコマンドそのもの(例 args: jj bookmark create feature-a -r @-)が残ります。
jj undo # 直前の操作を取り消す(続けて打つとさらに1つ前へ)
jj redo # 取り消しをやり直す
jj op log --limit 5 # 操作ログを見る
jj op restore <操作ID> # 任意の時点のリポジトリ状態へ戻す
0.33.0で jj undo は「連続」型になりました。それまでは2回続けて打つと、1回目の取り消しをさらに取り消して元に戻るだけでした。現在は打つたびに1つずつさかのぼり、戻しすぎたら jj redo で進めます。古い記事の「undoは1回しか効かない」という説明は現行版には当てはまりません。操作ログはGitのreflogと違ってブックマークやリモート追跡の状態も含むため、push前であればブックマークの付け間違いもまとめて戻せます。
古い解説が動かない理由:版ごとの破壊的変更
jj の日本語解説は2024〜2025年に書かれたものが多く、そのまま打つとエラーになったり、意味の無いフラグを付けたりすることになります。CHANGELOGから、入門者が踏みやすい変更だけを抜き出しました。
| 版(公開日) | 変更 | 古い記事の書き方 |
|---|---|---|
| 0.22(2024-10) | branch を bookmark に改名 | jj branch create |
| 0.33(2025-09) | undo が連続型に・redo 追加 | undo は1回だけ |
| 0.34(2025-10) | colocate が既定に | jj git init --colocate |
| 0.36(2025-12) | rebase の -d を -o に改名 |
jj rebase -d |
| 0.36(2025-12) | --allow-new 非推奨 |
jj git push --allow-new |
| 0.42(2026-06) | --allow-new を削除 |
同上(エラーになる) |
| 0.45(2026-09) | config --user の書き込み先 |
対話で選ぶ前提 |
-d は旧名として当面は残されており、CHANGELOGは「異例に長い非推奨期間」を置くと書いています。一方 --allow-new は既に削除済みで、0.42以降は指定するとエラーになります。調べ物で見つけたコマンドが動かないときは、まず記事の日付と jj --version を突き合わせ、公式ドキュメントの docs.jj-vcs.dev/latest で確認するのが確実です。STORES Product Blog「Gitの代わりにJujutsuを使い始めて1ヶ月」でも、生成AIに聞いたrebaseの -r と -s の説明が誤っていて1時間ほど失ったと報告されています。
Jujutsuを採用すべきでない場面:submodule・LFS・フック
公式ドキュメントのGit互換性一覧で「No」とされている機能を日常的に使うリポジトリでは、jj を主に使う運用は勧めません。
- submodule:作業コピーに現れません(データが失われることはない)。submoduleを更新するリポジトリでは、その操作だけGitに戻ることになります。
- Git LFS:非対応(issue #80)。LFSで大きな画像やモデルを管理しているリポジトリでは、LFSの取得・更新をGitで行う運用が残ります。
- Gitフック:非対応(issue #405)。pre-commitでlinterや秘密情報の検知を走らせている場合、jj からのコミットではそれが動きません。CI側で同じ検査を必ず通す構成になっていないなら導入を見送るべきです。
- git worktree:非対応。代わりに
jj workspaceで1つのリポジトリから複数の作業コピーを持てます。Git側の使い方はGit Worktree(ワークツリー)とはを参照してください。
逆に、小さな変更を積み重ねて1つずつレビューに出す使い方(スタックしたプルリクエスト)には向いています。下のコミットを直すと上に積んだコミットが自動で付け替えられるため、Gitのように rebase -i を何度もやり直す必要がありません。チームの他のメンバーはGitのままで構わず、リモートから見て区別は付きません。試すだけなら既存リポジトリで jj git init し、やめたくなったら .jj ディレクトリを消して git switch main で元のブランチに戻れます(手元で確認済み。.git 側の履歴は残ります)。残したい変更には、消す前に jj bookmark create で名前を付けておきます。
jjのTUI・GUI・VS Code拡張
jj tui というコマンドは存在しません。画面で操作したい場合は、いずれもコミュニティ製の次のツールを入れます(2026年9月28日時点で、jjui・lazyjj・GG・jj-fzfは同月中にもGitHubへの更新があり、Jujutsu Kaizenの最終更新は2026年5月)。
| ツール | 種類 | リポジトリ等 |
|---|---|---|
| jjui | TUI | idursun/jjui |
| lazyjj | TUI(Lazygit風) | Cretezy/lazyjj |
| jj-fzf | TUI(fzfベース) | tim-janik/jj-fzf |
| GG | デスクトップGUI | gulbanana/gg |
| Jujutsu Kaizen | VS Code拡張 | keanemind/jjk |
| VisualJJ | VS Code拡張 | visualjj.com |
GitHubのスター数はjjuiが約2,200、lazyjjが約1,200です。GitでLazygitに慣れている人はlazyjjから入ると操作の対応が取りやすいでしょう。同居リポジトリならVS Code標準のGit表示も動きますが、detached HEADとして表示されるため、ブックマークや変更の単位で見たいならjj専用の拡張を使います。
よくある質問
Jujutsuの読み方は?Googleの製品ですか?
「ジュジュツ」と読み、コマンド名は jj です。作者はGoogle社員で、Googleでの本人の専任プロジェクトですが、READMEに「Googleのサポート対象製品ではない」と明記されたコミュニティ主導のOSSです。
jjでgit cherry-pickに当たるコマンドは?
jj duplicate <コピー元> -o <コピー先> です。元のコミットと同じ内容・同じメッセージの新しいコミットが作られます。コミットを「移動」したいだけなら jj rebase -r <対象> -o <移動先> を使います。
jj logに全部の履歴が表示されないのはなぜ?
既定の表示範囲(revsets.log)が、今の作業コミット、書き換え可能なコミットとその近くの祖先、trunkだけを選ぶ式になっているためです。jj log -r :: で全履歴、jj log -r 'trunk()..@' でメインブランチから今の作業までが出ます。
jjの設定ファイルはどこにありますか?
Linux・macOSは ~/.config/jj/config.toml、Windowsは %APPDATA%\jj\config.toml です。jj config path --user で実際の場所を、jj config edit --user でエディタを開けます。環境変数 JJ_CONFIG を設定するとこれらの場所は読まれなくなります。
Jujutsuをやめて普通のGitに戻せますか?
同居(colocate)で使っていれば戻せます。リポジトリ直下の .jj ディレクトリを削除し、git switch main などでブランチに戻るだけです。jj で作ったコミットは既に .git に書かれているため消えませんが、ブックマークを付けていないコミットはGitからはブランチの無いコミットに見えるので、削除前に jj bookmark create で名前を付けておきます。