mcpField
J
jujutsu

jujutsu

github.com/danverbraganza開発81129 回インストール20 週間前に更新
リポジトリ

jujutsu について

jujutsu は、コーディングエージェント向けの Jujutsu(jj)バージョン管理ガイドです。可変コミット、自動リベース、Git 互換のワークフローに加え、非対話型環境でのコマンド実行と確認方法を説明します。

主な機能

  1. 01可変コミットと自動リベース
  2. 02revset によるコミット選択
  3. 03コミットの整理と変更の吸収
  4. 04ブックマークとワークスペースの管理
  5. 05Git リポジトリとの連携
  6. 06エージェント環境での操作指針

活用シーン

  1. 01jj リポジトリの履歴確認と編集
  2. 02作業をアトミックなコミットに整理
  3. 03複数ワークスペースでの並行作業
  4. 04Git の変更の取得とプッシュ

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/danverbraganza/jujutsu-skill --skill jujutsu

インストール後、Claude Code で/jujutsuを入力して読み込まれたか確認します。

詳細

Jujutsu (jj) バージョン管理システム

このスキルは、変更可能なコミットと自動リベースに対応した Git 互換の VCS、Jujutsu を使った作業に役立ちます。

jj v0.37.0 でテスト済み — 他のバージョンではコマンドが異なる場合があります。

重要:自動化/エージェント環境

エージェントとして実行する場合:

  1. コマンドがインタラクティブなページャー(less など)を開いてエージェントが停止するのを防ぐため、必ず --no-pager を使用してください。
# Always use --no-pager on commands that produce output
jj --no-pager log          # NOT: jj log
jj --no-pager diff         # NOT: jj diff
jj --no-pager show <id>    # NOT: jj show <id>
  1. エディターのプロンプトに頼らず、メッセージをインラインで指定するために必ず -m フラグを使用してください。
# Always use -m to avoid editor prompts
jj desc -m "message"      # NOT: jj desc
jj squash -m "message"    # NOT: jj squash (which opens editor)

エディターを使うコマンドは、非インタラクティブ環境では失敗します。

  1. 変更後(squash、abandon、rebase、restore)、jj st で操作を確認し、成功したことを確かめてください。

基本概念

作業コピーはコミットです

jj では、作業ディレクトリは常にコミット(@ として参照)です。jj のコマンドを実行すると、変更は自動的にスナップショットされます。ステージングエリアはありません。

jj commit を実行する必要はありません。

コミットは変更可能です

重要:git とは異なり、jj のコミットは作成後も自由に変更できます。新しいコミットを作成せずに、説明の更新、変更のスカッシュ、リベース、吸収ができます。推奨される作業パターンについては、以下の「基本的なワークフロー」を参照してください。

Change ID と Commit ID
  • Change ID:コミットが書き換えられても維持される安定した識別子(tqpwlqmp など)です。コミットを参照する際はこちらを優先してください。
  • Commit ID:コミットの内容が変わると変更されるコンテンツハッシュ(3ccf7581 など)です。
Revset

jj は、コマンドでコミットを選択するために revset 言語を使用します。よく使う revset は次のとおりです。

  • @ — 作業コピーのコミット
  • @- — 作業コピーの親
  • ::@ — @ のすべての祖先
  • @:: — @ のすべての子孫
  • trunk()..@ — trunk と @ の間のコミット(自分のブランチ)
  • bookmarks() — ブックマークが付いたすべてのコミット

revset は -r フラグとともに使用します:jj log -r 'trunk()..@'

基本的なワークフロー

作業の開始:まず説明を記述し、その後にコードを書く

コードを書く前に、必ずコミットメッセージを作成してください:

jj st で空のリビジョンであることを確認してください。そうでない場合は、次のように入力します。

jj new
# First, describe what you intend to do
jj desc -m "Add user authentication to login endpoint"

# Then make your changes - they automatically become part of this commit
# ... edit files ...

# Check status
jj st
アトミックコミットの作成

各コミットは、1 つの論理的な変更を表す必要があります。コミットメッセージには次の形式を使用してください。

Examples:
- "Add validation to user input forms"
- "Fix null pointer in payment processor"
- "Remove deprecated API endpoints"
- "Update dependencies to latest versions"
履歴の表示
# View recent commits
jj --no-pager log

# View with patches
jj --no-pager log -p

# View specific commit
jj --no-pager show <change-id>

# View diff of working copy (use --git for familiar +/- format)
jj --no-pager diff --git

重要:jj diff の出力形式:デフォルトの jj diff 出力では、左右に行番号が並ぶ形式(例:26 26:)が使用されます。git の +/- 接頭辞形式とは大きく異なります。これは正常で正しい出力であり、破損していたり、古い内容が表示されていたりするわけではありません。ただし、混乱を避けるため、標準的な +/- 行を使った統一 diff 形式にするには、必ず jj diff --git を使用してください。

コミット間の移動
# Create a new empty commit on top of current
jj new

# Create new commit with message
jj new -m "Commit message"

# Edit an existing commit (working copy becomes that commit)
jj edit <change-id>

# Edit the previous commit
jj prev -e

# Edit the next commit
jj next -e

コミットの調整

変更のスカッシュ

現在のコミットの変更を親コミットに移動します。

# Squash all changes into parent
jj squash

注:jj squash -i はインタラクティブ UI を開くため、エージェント環境では停止します。使用しないでください。

コミットの分割

警告:jj split はインタラクティブで、エージェント環境では停止します。コミットを分割するには、jj restore で変更を取り出してから、個別のコミットを手動で作成してください。

変更の吸収

変更された行を最後に編集したコミットに、変更を自動的に振り分けます。

# Absorb working copy changes into appropriate ancestor commits
jj absorb
コミットの破棄

コミットを完全に削除します(子孫はその親にリベースされます)。

jj abandon <change-id>
操作の取り消し

直前の jj 操作を元に戻します。

jj undo

これにより、リポジトリは直前のコマンドを実行する前の状態に戻ります。誤って abandon、squash、rebase した場合などに役立ちます。

コミットのリベース

コミットを別の親に移動します。

# Rebase current branch onto a destination
jj rebase -d <destination>

# Rebase a specific revision (without descendants) onto a destination
jj rebase -r <change-id> -d <destination>

# Rebase a revision and all its descendants
jj rebase -s <change-id> -d <destination>

# Rebase onto trunk (common: update your branch to latest main)
jj rebase -d main
ファイルの復元

特定のファイルの変更を破棄するか、別のリビジョンからファイルを復元します。

# Discard all uncommitted changes in working copy (restore from parent)
jj restore

# Discard changes to specific files
jj restore path/to/file.txt

# Restore files from a specific revision
jj restore --from <change-id> path/to/file.txt

ブックマーク(ブランチ)の操作

ブックマークは、jj における git のブランチに相当します。

# Create a bookmark at current commit
jj bookmark create my-feature -r@

# Move bookmark to a different commit
jj bookmark move my-feature --to <change-id>

# List bookmarks
jj --no-pager bookmark list

# Delete a bookmark
jj bookmark delete my-feature

ワークスペース

ワークスペースとは、作業コピーと、それに関連付けられたリポジトリのことです。1つのリポジトリに複数のワークスペースを持つことができ、それぞれが独自の作業ディレクトリと作業コピーのコミット(@)を持ちながら、同じコミット、操作、ブックマークを共有します。これは git worktree に相当する jj の機能です。

あるワークスペースで時間のかかるビルドやテストを実行しながら、別のワークスペースで編集する場合に便利です。ワークスペースは通常ほとんど必要にならない機能です。以下の基本事項を超える内容については、公式ドキュメントを参照してください。

よく使うコマンド
# Create a new workspace (defaults: name = basename of path, parent = current @'s parent)
jj workspace add ../my-tests
jj workspace add --name tests -r <change-id> ../my-tests   # explicit name and base

# Inspect
jj --no-pager workspace list
jj workspace root [--name <ws>]

# Remove (does NOT delete files on disk — rm the directory separately)
jj workspace forget [<ws>]

# Rename current workspace
jj workspace rename <new-name>

jj log では、各ワークスペースの @ は <workspace-name>@ として表示されます。

主なセマンティクス
  • デフォルトでは分離されています。 jj workspace add は、新しいワークスペースに新規の空のコミットを割り当てます。ワークスペースは最初から @ を共有することはなく、ディスク上のファイルがワークスペース間でリアルタイムにミラーリングされることもありません。
  • コマンドの境界で反映されます。 jj の各コマンドは、現在のワークスペースのファイルをスナップショットし、操作ログを読み取るため、他のワークスペースで作成されたコミットやブックマークを確認できます。ファイルシステムの変更を監視する機能はありません。
  • 作業コピーが古くなった場合。 別のワークスペースによってこのワークスペースの @ が書き換えられた場合(例:jj squash、rebase、abandon)、jj workspace update-stale を実行するまで、jj はこのワークスペースでのコマンド実行を拒否します。コマンドが更新の途中で中断された場合も、同じ方法で復旧できます。
  • @ の共有にはリスクがあります。 jj edit <id> を使うと、警告なしに2つのワークスペースが同じ変更を指すことがあります。一方で変更を加えると、もう一方は古い状態になります。古い状態のワークスペースにスナップショットされていない編集があった場合、update-stale はそれを分岐したコミット(同じ変更 ID を持ち、jj log では xyz?? と表示されます)として保持するため、解決が必要です。両方のワークスペースが読み取り専用でない限り、@ の共有は避けてください。
エージェント向けガイダンス
  • jj workspace list には常に --no-pager を指定してください。
  • 別のワークスペースですでに @ になっている変更を jj edit しないでください。意図しない分岐の主な原因です。
  • jj workspace forget <name> も実行せずに、ワークスペースのディレクトリを rm -rf で削除しないでください。

Git 連携

既存の Git リポジトリを使用する
# Clone a git repository
jj git clone <url>

# Initialize jj in an existing git repo
jj git init --colocate
リモートの変更をフェッチする
# Fetch all branches from the default remote
jj git fetch

# Fetch from a specific remote
jj git fetch --remote <remote-name>

# Fetch specific branches
jj git fetch -b <branch-name>

フェッチ後、作業を更新されたトランクにリベースします:jj rebase -d main

jj と git を切り替える(コロケーションされたリポジトリのみ)

このセクションはコロケーションされたリポジトリ(.jj/ と .git/ の両方が存在するリポジトリ)にのみ適用されます。コロケーションされていないリポジトリでは、git コマンドを使わないでください。jj の状態が破損します。

コロケーションされたリポジトリでは、注意して jj と git の両方のコマンドを使用できます。

git モードに切り替える(例:マージのワークフローの場合):

# First, ensure your jj working copy is clean
jj st

# Then checkout a branch with git
git checkout <branch-name>

jj モードに戻す:

# Use jj edit to resume working with jj
jj edit <change-id>

重要な注意事項:

  • jj の作業コピーが git の HEAD と異なる場合、git は未コミットの変更について警告することがあります。
  • git に切り替える前に、jj で作業がコミット済みであることを必ず確認してください。
  • git の操作後、jj は次のコマンド実行時に変更を検出して取り込みます。
変更をプッシュする

ユーザーから変更のプッシュを依頼された場合:

# Push a specific bookmark to the remote
jj git push -b <bookmark-name>

# Example: push the main bookmark
jj git push -b main

プッシュする前に、以下を確認してください:

  1. ブックマークが正しいコミットを指していること(ブックマークは git のブランチのように自動で進みません)
  2. コミットが整理され、アトミックであること
  3. ユーザーがプッシュを明示的に依頼していること

重要:git のブランチとは異なり、jj のブックマークは新しいコミットを作成しても自動で移動しません。プッシュする前に手動で更新する必要があります。

# Move an existing bookmark to the current commit
jj bookmark move my-feature --to @

# Then push it
jj git push -b my-feature

変更に対応するブックマークがない場合は、まず作成してください。

# Create a bookmark at the current commit
jj bookmark create my-feature

# Then push it
jj git push -b my-feature

競合の処理

jj では競合を含むコミットを作成でき、後から解決できます。

# View conflicts
jj st

エージェントによる競合解決:jj resolve(対話型)は使用しないでください。代わりに、競合マーカーを削除するよう競合ファイルを直接編集し、その後 jj st を実行して解決を確認してください。

コミット品質の維持

重要:コミットは変更可能なため、作業完了とする前に必ず調整してください。

  1. コミットを確認する:jj --no-pager show @ または jj --no-pager diff --git
  2. アトミックですか? 1つのコミットにつき、論理的な変更を1つにします
  3. メッセージは明確ですか? 句点を付けず、文頭を大文字にした命令形の動詞句を使います。例:「ログインエンドポイントを追加する」「決済処理のヌルポインターを修正する」「非推奨の API エンドポイントを削除する」
  4. 無関係な変更はありませんか? jj restore を使って変更を切り離し、別のコミットを作成します
  5. 変更を別の場所に含めるべきですか? jj squash または jj absorb を使います

クイックリファレンス

操作コマンド
コミットの説明を設定jj desc -m "message"
ステータスを表示jj st
ログを表示jj --no-pager log
差分を表示jj --no-pager diff --git
新しいコミットjj new -m "message"(最初に jj st を実行します。@ が空の場合は省略します)
コミットを編集jj edit <id>
親コミットにスカッシュjj squash
自動振り分けjj absorb
リベースjj rebase -d <destination>
コミットを破棄jj abandon <id>
直前の操作を元に戻すjj undo
ファイルを復元jj restore [paths]
ブックマークを作成jj bookmark create <name>
リモートからフェッチjj git fetch
ブックマークをプッシュjj git push -b <name>
ワークスペースを追加jj workspace add <path>
ワークスペースを一覧表示jj --no-pager workspace list
ワークスペースを登録解除jj workspace forget [name]
古くなった作業コピーを修正jj workspace update-stale

ベストプラクティスのまとめ

  1. 最初に説明する:コーディングを始める前にコミットメッセージを設定します
  2. コミットごとに変更は1つ:コミットをアトミックにし、焦点を絞ります
  3. 変更 ID を使う:書き換え後も変わりません
  4. コミットを調整する:変更可能性を活用して、履歴をきれいに保ちます
  5. ワークフローを活用する:ステージングエリアもスタッシュもなく、コミットするだけです

コメント