but について
GitButler の `but` コマンドラインでバージョン管理を行うコーディングエージェント向けのスキルです。変更の選択や ID の扱い、共有作業への意図しない変更を防ぐ手順を説明します。
主な機能
- 01タスクに応じたコマンド選択
- 02変更とコミット ID の指針
- 03安全な変更のルール
- 04一般的な GitButler ワークフロー
活用シーン
- 01選択した変更を新しいブランチにコミット
- 02main を基に作業スペースを更新
- 03コミットとブランチの構成を変更
- 04他のエージェントの編集を含めない
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ gitbutlerapp/ gitbutler --skill butインストール後、Claude Code で/butを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
AGENTS.mdREADME.mdstub.mdreferences/concepts.mdexamples.md詳細
翻訳後に原文が更新されています。最新の内容は原文をご確認ください。
GitButler CLI スキル
デフォルトのバージョン管理インターフェースとして GitButler CLI (but) を使用します。
ここから始める
タスクに応じて、最も対象を絞った最初のコマンドを選びます。定型的なステータス確認は避けてください。
# Selected dirty files/hunks:
but diff
# Commit order, branch/stack placement, conflict overview:
but status
# File/hunk IDs, per-commit files, amend/split details:
but status -fv
# Details for one known branch or commit:
but show <id>
簡潔な出力にタスクで必要なファイル/ハンクの詳細が含まれていない場合を除き、but status を実行してから but status -fv を実行しないでください。
「新しいブランチに変更の一部/特定の変更だけをコミットする」場合は、次のファストパスを使用します。
but diff
but commit -b <branch> -m "<msg>" <id> <id>
but commit -b <branch> ... は、ブランチが存在しない場合に作成し、作成されたコミットを表示します。結果から得られないワークスペース情報がタスクに必要な場合を除き、別途 but branch new、ステータスコマンド、または確認用の diff を実行しないでください。
ID
but diff/but status の各行の先頭のトークンが、その行の ID です。コマンドで ID が必要な場合は、現在の出力からそのままコピーしてください。決して ID をハードコードしたり、作り出したりしないでください。ID の有効期間はエンティティごとに異なります。
- 変更とソースは、位置指定のスペース区切り ID です(
but commit -b feat -m "msg" uvw:2e4 uvw:e2c)。未コミットのハンク ID は<file-id>:<hunk-id>と記述します(例:uvw:2e4。but diffの出力からそのままコピーします)。コロンの後の部分はハンクの ID であり、行範囲ではありません(uvw:16-40は無効です)。--changes/--hunk/--idsのようなフラグを作り出したり、行範囲を渡したり、ID をカンマ区切りにしたりしないでください。uvw,qyoは 1 つの ID として解析され、失敗します。 but diffは例外で、対象を最大 1 つ受け付けます。引数なしのbut diffは、未コミットのファイルをすべて表示します。コミット済みファイルやその他のエンティティは、一度に 1 つずつ調べてください。but diff <id> <id>は実行しないでください。- コミット済みファイルは
<commit-id>:<file-id>です(例:mzm:uvw。各コミットの下に表示されます)。コミット済みハンクは<commit-id>:<file-id>:<hunk-id>で、but diff <commit-id>に表示されます。@は未コミット領域を意味します。 - コミット ID は、履歴の編集(
amend、squash、move、uncommit、reword)後も保持される、安定した変更 ID です。変更 ID のないコミット(例:上流のみのコミット)は sha のプレフィックスで始まり、重複を区別するために#N接尾辞付きの参照が使われます。どちらも履歴の編集後は古くなり、古くなった sha は誤ったコミットを黙って解決する場合があります。詳細表示のコミット行にある(sha …)は参考情報です。コマンドに渡さないでください。 - ブランチの短縮 ID は、スナップショット内でのみ有効なセレクターです。ブランチを対象とする変更操作には完全なブランチ名を使用してください。短縮 ID が安全なのは、直後の読み取り専用の確認に限られます。
- 1 回の diff の読み取りからコピーしたファイル/ハンク ID は、連続するコミット処理でも通常は引き続き使用できます。解決できなくなった場合は、
but diffを再実行して再試行してください。
連続実行: 変更操作の出力はデフォルトでは簡潔なため、1 回の確認結果をもとに && で変更操作を連続実行できます。変更操作でブランチの短縮 ID を連鎖して使わないでください。完全なブランチ名を使用します。次の手順で、変更操作の結果からは得られないワークスペース ID や詳細が必要な場合に限り、--status-after を追加してください。連続する but commit 呼び出しは記述順に積み重なります。最初のものが最も古く、その後のものが順に上に重なります。関係するすべてのコミット参照が変更 ID の参照であれば、履歴編集を順に実行できます。参照が sha ベースまたは #N 接尾辞付きの場合、あるいは次のコマンドで新しく発行された ID が必要な場合は、--status-after を付けて 1 つずつ実行してください。but uncommit <id> && but diff の連続実行は安全です。引数なしの diff は uncommit の出力から ID を必要としないためです。
必ず守るルール
- すべての書き込み操作には
butを使用してください。git add、git commit、git push、git checkout、git merge、git rebase、git stash、git cherry-pickは絶対に実行しないでください。唯一の例外は、コンフリクトしたサブモジュールの解決モードで一方を選択する場合です(「コンフリクトしたコミットを解決する」を参照)。ユーザーがgitの書き込みコマンドを指定した場合は、butに置き換えて実行してください。リンクされたワークツリーから実行すると、メインのワークツリーと同じワークスペースおよび ID が表示され、@は引き続きメインのワークツリーの変更を意味します。引数なしのbut commitまたはbut diffは、そのワークツリーの変更を対象とし、<worktree>:@を使えばどこからでもそれらの変更を指定できます。 - 変更コマンドは、ワークスペースの状態を後ろに付け加えず、結果を出力します。次のステップで変更後のワークスペース ID や詳細が必要な場合に限り
--status-afterを追加してください。それ以外の場合は変更コマンドの結果を信頼し、状態確認や差分確認を実行しないでください。 (merged upstream)の印が付いたブランチは取り込み済みです。新しい作業は別のブランチで始めてください。この印だけではbut pullによってブランチが削除されるとは限りません。まずbut pull --checkを実行してください。but pullは[integrated](「上流に統合され、ローカルから削除された」)と表示されたブランチだけを削除し、それ以外はリベースして適用状態のままにします。適用状態のままの取り込み済みブランチを解除するには、but discardではなくbut unapply <branch>を使用してください(スタック全体に作用します。but apply <branch>で再適用できます)。pushおよび変更操作(commit、amend、squash、uncommit、reword、move)は取り込み済みのブランチやコミットを拒否し、absorbは通知を出してそれらをスキップします。また、commitはデフォルトの対象を選ぶ際にそれらをスキップします。- 非対話型の CLI ワークフローでは、通常のコマンドの実行中に進捗を説明しないでください。必要な
butコマンドを実行し、最後に簡潔な要約を提示してください。 - 試行錯誤的にヘルプを呼び出すより、このスキルと
but skill referenceを優先してください。必要な構文が分からない場合、またはコマンドが失敗した場合は<command> --helpを使用してください。未文書化のコマンドを探す必要が本当にある場合に限り、トップレベルのヘルプを使用してください。
コマンドパターン
- Git リポジトリを初期化する:
but init(現在のディレクトリ)またはbut -C <path> init。非対話型です。コミット、リモート、GitButler ワークスペースは作成されません。既存のリポジトリは変更されません。 - コミットする:
but commit -b <branch> -m "<msg>" <id> <id>—-b <branch>は、存在しない場合にブランチを作成します - 未コミットの変更をすべてコミットする:
but commit -b <branch> -m "<msg>"(ID は省略します) - 1 つの差分から複数のコミットを作成する:
but commitの呼び出しを&&で連結します(コミットは古いものから順に積み重なります) - 特定の履歴位置にコミットする:
--above <commit-or-branch>または--below <commit-or-branch>(同時には指定できません)。ブランチを指定する場合は、-b <new-name>を追加して新しいブランチに名前を付けます。指定しない場合は名前が自動生成されます。名前は既存のものであってはなりません。コミットまたはワークツリーを対象にする場合は、名前を指定しない場合でも-bと組み合わせないでください。 - 複数の スタック が適用されている場合、ターゲットの指定が必須です。指定しないと
but commitは "Unclear where to commit. Found more than one stack" というエラーで失敗します。複数のブランチが一緒に積み重なっていても 1 つのスタックとして扱われます。ターゲットを指定しないコミットはスタックの最上位ブランチに暗黙的に追加されるため、ブランチを指定する必要がある場合は必ず-bを渡してください。 but commitには必ず-m "<msg>"(またはヒアドキュメントで-F -、リポジトリ外のファイルを指定する-F <file>、もしくは--no-message)を渡してください。また、ソースがコミットまたはブランチである場合は、ターゲットが@でない限りbut squashにも渡してください。これらは新しいメッセージを作成します。フラグを指定しない場合、エージェント実行ではコマンドが作成したメッセージ(but commitでは空、but squashではソースのメッセージを連結したもの)がそのまま使われ、ターミナルではエディターが開きます。未コミットの変更またはコミット済みの変更をソースにするスカッシュでは、ターゲットのメッセージが再利用されるためフラグは不要です。@へのスカッシュではメッセージフラグは一切受け付けられません。- 修正する:
but amend -t <commit-or-branch> <file-or-hunk-id> <file-or-hunk-id>— ブランチを指定すると、そのブランチの最新コミットが対象になります - コミットを取り消す:
but uncommit <commit-id>(コミット全体)、but uncommit <branch>(すべてのコミットを取り消してブランチを削除)、but uncommit <commit-id>:<file-id>(コミット済みファイル)、またはbut uncommit <commit-id>:<file-id>:<hunk-id>(コミット済みハンク)。コミット済みのファイルとハンクは混在させられますが、すべて同じコミットに含まれている必要があります - 空のコミットを挿入する:
but commit --empty -b <branch> -m "<msg>" - 名前を指定した新しいブランチにピックする:
but pick <commit-sha> --above <branch> -b <new-name>(--belowも使用できます)。名前は既存のものであってはなりません。-bはコミットまたはワークツリーのターゲットと組み合わせられません。 - コミットをスカッシュする:
but squash <source-commit-id> [<source-commit-id>...] -t <target-commit-id> -m "<msg>" - コミット済みの変更を既存のコミットまたは
@に移動する:コミット済みファイルの場合はbut squash <commit-id>:<file-id> -t <commit-id-or-@>、コミット済みハンクの場合はbut squash <commit-id>:<file-id>:<hunk-id> -t <commit-id-or-@>。すべてのソースは同じコミットに含まれている必要があります - コミット済みの変更を、選択した位置に新しいコミットとして移動する:コミット済みファイルの場合は
but move <commit-id>:<file-id> --above <commit-or-branch> -m "<msg>"、コミット済みハンクの場合はbut move <commit-id>:<file-id>:<hunk-id> --above <commit-or-branch> -m "<msg>"(--below、--branch、--unstackも使用できます) - 選択したコミット済み変更を分割し、ソースのすぐ上に新しいコミットを作成する:
but split <committed-file-or-hunk-id> [<committed-file-or-hunk-id>...] -m "<msg>" but splitと、コミット済み変更を対象にするbut moveでは、-m/--messageを使って新しいコミットに直接名前を付けます。-mを複数回指定した場合、値は空行で連結されます。複数行のメッセージを渡す場合は、-mの代わりにヒアドキュメントで-F -を使うか、リポジトリ外のファイルを指定して-F <file>を使います。どちらも省略すると、エディターを開かずに空のメッセージでコミットが作成されます。but move -mと-Fは、コミット全体またはブランチをソースにする場合は受け付けられません。- ブランチ全体を 1 つのコミットにスカッシュする:
but squash <branch> -m "<msg>"(-tは不要です) - コミットを取り消してブランチを削除する:
but uncommit <branch> - コミットの順序を変更する:
but move <commit-id> --below <commit-id>(逆方向には--aboveを使用します。ブランチ名ではなくコミット IDを指定してください) - ブロックの順序を変更する:
but move <commit-id> <commit-id> --below <following-commit-id>または--above <preceding-commit-id>(どちらのアンカーにも、スペース区切りで複数のソースを指定できます) - コミットをブランチの先頭に移動する:
but move <commit-id> -b <branch> - コミットまたはコミット済みの変更を、名前を指定した新しいブランチに移動する:
but move <source> --above <branch> -b <new-name>(--belowも使用できます)。独立したブランチにするにはbut move <source> --unstack -b <new-name>を使用します。自動生成された名前を使う場合は-bを省略します。ブランチをソースとして積み重ねる場合、または積み重ねを解除する場合は、名前を指定できません。 - ブランチを積み重ねる:
but move <branch-name> --above <target-branch-name>(ブランチ名は省略せずに指定してください) - ブランチの積み重ねを解除する:
but move <branch> --unstack - 破棄する:
but discard <id> [<id>...]— ブランチ、コミット、コミット済みの変更、未コミットの変更、またはすべての未コミット変更を示す@を指定できます - プッシュする:
but push <top-branch>— 選択したブランチとその祖先をプッシュします。スタックを更新するには、その最上位ブランチを一度選択すればよく、繰り返し実行しないでください。対話型でない実行時に引数なしのbut pushを実行すると、プッシュされていない作業がすべてプッシュされます。スタックごとに 1 回(祖先を含む、未プッシュの最上位ブランチ)プッシュされるため、出力にはブランチごとではなくスタックごとに 1 件表示されます。いずれかのスタックで失敗すると終了コードは 0 以外になります。すでにプッシュ済みのスタックはそのままなので、失敗を修正した後に再実行しても安全です(最新のスタックはスキップされます) - プルする(ターゲットからワークスペースを更新する):
but pull— 結果は出力に表示されます。プレビューが実際に必要な場合は、更新せずにプレビューするためbut pull --checkを実行します - PR を作成する:
but pr new <branch-name> [-m "Title..."] [-F - | -F <file>] [-t] [--draft]— 最初に自動でプッシュされるため、その前にbut pushを実行しないでください
タスクの手順
main からワークスペースを更新する
「main から最新の変更を取得」「このワークスペースを更新/同期」「main にリベース」、または「main をプル」と依頼された場合:
but pull— 1 つのコマンドで実行でき、事前確認は不要です。出力に処理後の状態が表示され、未コミットの変更と競合する場合は安全に処理を拒否し、but undoで元に戻せます。- コミットに競合がある場合は、表示された手順に従って古いものから解決します:
but resolve <commit>を実行し、ファイルを編集してからbut resolve finishを実行します。結果には、次に競合しているコミットの現在の ID が表示されます。タスクで処理後のワークスペース全体が必要な場合に限り、最後の競合を解消する予定のfinishに--status-afterを追加します。競合しているコミットが残っていないと表示されたら終了し、状態確認は実行しないでください。下位のコミットを完了すると、その上位のコミットがリベースされるため、常に下から順に作業します。
but pull --check は、更新せずに「競合するか」を確認します。通常の事前確認としては使わないでください。ユーザーがプレビューを求めている場合、リポジトリのポリシーで必要な場合、他のエージェントのブランチが動く可能性がある場合、または適用済みのブランチが直前に上流へマージされた場合に使用します(ルール 3 を参照)。
適用済みのブランチを最新のターゲットにリベースするには、but pull を使います。move、config target、unapply、または通常の git pull/git rebase は決して使わないでください。ステータスに表示されるベースは、最後に FETCH された状態です。git log で main(ローカルまたはリモート)がそのベースより進んでいる場合、それが but pull で FETCH して適用される変更です。ターゲットの設定が古いわけではなく、ターゲットの向き先を変えても解決にはなりません。プルでは未コミットの変更も引き継がれ、出力に処理後の状態が表示されます。未コミットの変更が競合して処理を拒否された場合は、それらを退避します:but commit -b <branch> -m "wip" <ids> を実行してから再度プルし、その後、退避したコミットに対して but uncommit を実行します(stash はありません。ファイルを手作業で元に戻さないでください)。
選択したファイルまたはハンクをコミットする
but diff— 未コミットの変更について、ファイル ID とハンク ID を表示します。先に引数なしのbut statusを実行しないでください。- ファイル全体をコミットする場合はファイル ID を使用し、ファイルの一部だけをコミットする場合はハンク ID(
<file-id>:<hunk-id>)を使用します。コミットしない ID は省略します。 but commit -b <branch> -m "<msg>" <id1> <id2>— ブランチが存在しない場合は作成されるため、事前にbut branch newを実行する必要はありません。- タスクで残っている変更を把握する必要がある場合は
--status-afterを追加します。それ以外の場合は、作成されたコミットの結果だけで十分です。
例外:同じ diff ハンクにコミットしたい編集とコミットしたくない編集がある場合、GitButler ではそのハンクを ID で分割できません。そのハンクの一部を未コミットのまま残す必要がある場合に限り、作業ツリーを一時的に編集して必要な行だけにし、その ID をコミットしてから、残りの行を復元して未コミットのままにします。
既存のコミットに修正を加える
but status -fv(またはbut show <branch-id>)— ファイル/ハンク ID と対象コミット ID を特定します。but amend -t <commit-id> <id> <id>— 対象コミットごとに 1 つのコマンドを実行します。複数の対象コミットについて、すべての対象が change-ID 参照の場合は amend を&&で連結します。それ以外の場合は、最新の参照を取得するために--status-afterを付けて 1 つずつ実行します。
既存のコミットを分割する
2 つに分割する場合は、選択したコミット済みのファイルまたはハンクを直接新しいコミットに移動します。
but diff <source-commit-id>— コミット済みファイルとハンクの ID を確認します。but split <committed-file-or-hunk-id> [<committed-file-or-hunk-id>...] -m "<message>"— ソースにはファイルとハンクを混在させられますが、すべて同じコミットに属している必要があります。このコマンドは、指定したコミットをソースの直前に作成し、選択されなかった変更と元のメッセージはソースに残します。新しいコミットに対する追加の reword は不要です。- 次の手順で、変更結果に含まれていないワークスペース ID や詳細が必要な場合に限り、
--status-afterを追加します。
置き換え用のコミットを 2 つより多く作成する場合は、残りのソースのコミット済み変更を使って but split ... -m "<message>" を繰り返します。コミット全体を再構築する場合は、以下の uncommit/recommit ワークフローを使用します。
- ソースコミット、ブランチ名、または配置アンカーが必要な場合は、
but status -fvを実行します。 but uncommit <source-commit-id> && but diffを 1 回のシェル呼び出しで実行すると、コミットの変更を確認でき、結果のファイル ID とハンク ID が表示されます。- 置き換え用の内容は、古いコミット済み diff ではなく、変更状態の diff から選びます。
- ユーザーの指示から希望する時系列順を判断し、置き換え用のコミットは古いものから順に、
but commitの呼び出しを連結して作成します。but statusはコミットを新しいものから順に表示しますが、それに合わせて順序を逆にしないでください。-b <branch>を指定すると、新しい各コミットはそのブランチの先頭に置かれます。分割したコミットの上にコミットがあった場合、置き換え用のコミットは保持されたコミットの上に配置されます。 - そのブランチのコミットを置き換え用コミットの上に残す必要がある場合は、アンカーに無理に合わせるのではなく、保持するブロックをまとめて先頭に戻します。
--above <top>/--below <top>をアンカーとして使用しないでください(sha/#Nアンカーは、挿入のたびに履歴が書き換えられるため古くなります)。ブロックをまとめて移動し、内部の順序を保ちます。コミットの連鎖に&& but move <preserved-id> [<preserved-id>...] -b <branch>を追加します。手順 1 の Change-ID 参照は引き続き有効です。保持する参照が sha ベースまたは#N付きの場合は、最新の出力を取得してから操作します。 - 不要な変更はコミットせずに残します。古いものから順に作成した置き換え用コミットは、status では新しいものから順に表示されます。これは正しいため、順序を並べ替えないでください。結果の順序を確認する必要がある場合は、最後の変更操作に
--status-afterを追加します。
コミットを並べ替える
but status はコミットを新しいもの/先頭から順に表示しますが、タスクの仕様では履歴が古いものから新しいものの順に記載されることがよくあります。移動する前に順序を読み替えてください。
- コミット ID を取得するため、
but statusを 1 回実行します(ファイルの詳細も必要な場合に限り-fvを使います)。 but move <source> --below <target-commit>は、ソースをbut status上でターゲットの直下(古い順の履歴では古い側)に配置します。--aboveは直上(新しい側)に配置します。but move <source> -b <branch>は、ソースをブランチの先頭/最新位置に移動します。- 隣接するブロックを移動する場合は、アンカーをどちらに置くかにかかわらず、移動を 1 回だけ実行します。
but move <block-id> <block-id> --below <following-commit-id>またはbut move <block-id> <block-id> --above <preceding-commit-id>を使います。ブロックの外側にあるアンカーを選びます。ソースの順序は問いません。ブロックの内部順序は保たれます。結果の順序を確認する必要がある場合は--status-afterを追加します。アンカーやブロックのメンバーを再度移動しないでください。 - それ以外の並べ替えでは、必要最小限の移動を行います。
コミットをスカッシュする
- コミット ID と順序を確認するため、
but statusを実行します。 - ソースを位置引数で指定し、結果/ターゲットのコミットを
-tで指定します。but squash <source> [<source>...] -t <target> -m "<new message>"を実行します。 - ブランチ全体を 1 つのコミットにまとめるには、
-tを指定せず、ブランチだけを渡します。but squash <branch> -m "<new message>"を実行します。 - 独立した複数のグループは、1 回の status 確認結果を使って続けて処理できます(ターゲットの Change-ID 参照は維持されます)。新しい/先頭側のグループを先に処理してください。参照が sha ベースまたは
#N付きの場合に限り、新しい参照を取得します。 - 結果の履歴を確認する必要がある場合は、最後の squash に
--status-afterを追加します。別途 status を実行して再確認しないでください。
既存のブランチをスタックする
既存のブランチを別のブランチに依存させるには、but move <child-branch-name> --above <parent-branch-name> を実行します(ブランチ名は省略せずに指定してください。コミットの並べ替えにはコミット ID を使用します)。スタックを解除するには、but move <branch-name> --unstack を実行します。
uncommit + branch delete + branch new --above でスタックしないでください(削除後も git のブランチ名は残り、作業が失われます)。また、スタックを解除するために but undo を使用しないでください。
プルリクエストを作成または管理する
but pr new <branch-name> は選択したブランチとその祖先をプッシュし、1 回の操作で PR を作成します。事前に but push を実行する必要はありません。エディターを開かずに済むよう、heredoc を指定した -F -、-F <file>(1 行目がタイトル)、-t、または実際の改行を含む -m(zsh/bash の場合:-m $'Title\n\nBody')を指定してください。メッセージをリポジトリ内のファイルに書き込まないでください。次の but commit でコミットされてしまいます。forge の認証情報がない場合は、but config forge auth を実行してください。
スタックされたブランチの PR を作成する場合は、gh pr create ではなく but pr を使用してください(PR のベースとスタックのメタデータを設定するのは but pr だけです。gh pr create を使用すると壊れてしまいます)。スタック全体を公開するには、but pr new <top-branch-name> -t を実行します。but pr auto-merge|set-draft|set-ready <selector> で管理できます。セレクターには、ブランチ名、現在のブランチまたはスタックの CLI ID、数値のレビュー ID を指定できます。詳細は but skill reference を参照してください。
別のブランチとの依存関係の競合
別のブランチのコミットを基にした変更は、独立したブランチには反映できません。but commit と but amend はアトミックに失敗します(「Cannot commit: N changes could not be applied」)。エラーには、適用できなかった各変更が依存するブランチとコミットが示されます。何もコミットされず、-b ブランチも作成されません。
依存先のブランチが 1 つの場合、エラーの Hint に正確な復旧コマンドが示されます。既存のブランチを依存先の上にスタックするには but move <your-branch> --above <dependency-branch> を、対象のブランチがまだ存在しない場合は but branch new <name> --above <dependency-branch> を実行します。コマンドを実行してから、元のコマンドを再試行してください。エラーに依存先が示されているものの Hint がない場合(依存先のブランチが複数ある場合、または依存先が対象のブランチ自体の場合)は、配置を選択する前に but status -fv を実行して、依存するコミットがどこにあるかを確認してください。
復旧コマンドが失敗した場合、回避策として uncommit、squash、undo を試さないでください。but status -fv を再実行し、両方のブランチが存在して適用されていることを確認してから、正確なブランチ名を指定して再試行してください。
競合したコミットを解決する(pull、move、並べ替えの後)
解決中に git add、git commit、git checkout --theirs/--ours、または Git の書き込みコマンドを使用しないでください。 but resolve コマンドとファイルの直接編集のみを使用してください。以下の編集モードで競合したサブモジュールを扱う場合に限り、例外となります。
GitButler では、競合によって操作が中断されることはありません。リベースは常に完了し、競合したコミットには but status で {conflicted} のマークが付きます。競合したコミットは、履歴編集コマンド(move、discard など)の警告、but pull の概要、または but status で確認してください。モードに入らず、競合を 1 件ずつ解決してください。ブランチごとに古いコミットから順に進めます。手順は次のとおりです。
but resolve conflicts <branch>— そのブランチで競合している最も古いコミットの競合を、ファイルごとに番号を付けて表示します。各競合には、ours(コミットのリベース先となった新しいベース)、base(共通の祖先)、theirs(コミット自体のバージョン)の3つのセクションがあります。ブランチを指定しない場合は、最初に見つかった競合中のブランチを選び、そのブランチを通知します。また、ほかにも競合中のコミットがある場合は、その旨を出力します。- 解決を1つずつコマンドで適用します。
- マージした内容/両方を組み合わせた内容(よくあるケースです):標準入力(ヒアドキュメント)経由で
but resolve apply <path>:<N>に渡すか、--file <f>を指定します。内容は競合領域全体を置き換えます。競合マーカーは絶対に含めないでください。 - 片方をそのまま採用する場合:
but resolve apply <path>:<N> --oursまたは--theirsを指定します(<path>のみを指定すると、そのファイルのすべての競合に適用されます)。 - 1つの競合の解決を設定済みの AI モデルに委任する場合:
but resolve apply <path>:<N> --aiを指定します。ただし、コンテキストを把握している場合は、自分でマージした内容を優先してください。 applyはconflictsと同じデフォルトのコミットを対象にします。競合中のブランチが複数ある場合は、--commit <branch>で対象を指定してください。
- マージした内容/両方を組み合わせた内容(よくあるケースです):標準入力(ヒアドキュメント)経由で
- 競合がないと報告されるまで、手順1に戻ります。ここではコミット ID は安定しません。適用のたびにコミットが書き換えられますが、ブランチ名は変わらないため、すべてブランチ名で指定し、コミット ID を記録しないでください。途中までの解決でも問題ありません。未解決の競合が残っているコミットは、該当する競合だけを残して
{conflicted}のままになります。
誤った解決は but undo で取り消せます。
but resolve <commit-id> --ai は、設定済みの AI モデルを使ってコミット全体を一度に解決します。コミットを指定せずに but resolve --ai を実行すると、競合中のすべてのコミットを古い順に解決します。これは代替手段としては許容できますが、通常はそのモデルよりもあなたのほうが適切なコンテキストを把握しているため、apply を使って自分で競合を解決することを優先してください。
解決内容に対してコードを実行する必要がある場合(そのコミット時点でのビルド/テストなど)に限り、編集モードを使用してください。
but resolve <commit-id>— 解決モードに入り、競合領域を表示します。- ファイルを編集して、すべての競合マーカー(
<<<<<<<、|||||||(共通の祖先のセクション)、=======、>>>>>>>)を削除し、正しい内容を残します。これを省略しないでください。競合中のコミットにbut amendを使用しないでください。- 競合中のサブモジュールにはマーカーがありません。コミット自体の側を採用する場合でも、未解決のままだと
but resolve finishは拒否されます。明示的に選択してください。サブモジュール内で採用するコミットをチェックアウトする(または置き換えるファイルを書き込む)操作をしてからgit add -- <path>を実行するか、git rm -- <path>で削除します。解決中に許可されている git の書き込みコマンドはこれらのみで、対象にできるのはfinishが指定するパスだけです。git commitは絶対に実行しないでください。サブモジュールのディレクトリが空または存在しない場合は、git addを実行しないでください(存在しないサブモジュールに対して実行すると、その削除がステージされます)。必要な解決内容の編集は残し、競合を報告してください。but resolve cancel --forceは解決を放棄して編集内容を破棄します。編集内容を破棄してよい場合に限って使用してください。
- 競合中のサブモジュールにはマーカーがありません。コミット自体の側を採用する場合でも、未解決のままだと
but resolve finishは、残っているマーカー、コミットされていない変更、競合中の残りすべてのコミット、および現在実行すべき正確なbut resolve <id>コマンドを報告します。タスクでワークスペース全体の完成状態が必要な場合に限り、最後の競合を解消する予定のfinishに--status-afterを追加してください。競合中のコミットが残っていないと表示されたら、そこで終了し、状態確認は実行しないでください。キャンセルする場合はbut resolve cancelを実行してください。- 残りの競合中のコミットについて、古いものから順に繰り返します。下位のコミットを終了すると、その上位のコミットはリベースされます。
コミットされていないファイルの競合
but status は、未解決のマージ競合があるコミットされていないファイルに {conflicted} を付けて表示します。これらはコミット可能な変更から除外され、but resolve モードの対象外です。ファイルを希望する内容に編集する(または削除する)と、but resolve <path>... でその状態を解決済みとして記録できます。その後は通常のコミットされていない変更として表示されます。
Git と but の対応表
| git | but |
|---|---|
git status | ブランチ/スタック/コミットの概要には but status、ファイル/ハンクの詳細には but status -fv、選択した未コミットの変更には but diff |
git add + git commit | but commit -b <branch> -m ... <ids> |
git checkout -b + commit | but commit -b <new-branch> -m ... <ids> |
git push | but push <branch-name> |
git rebase -i | but move、but squash、but reword |
git rebase --onto | but move <branch> --above <new-base> |
git checkout -- <file> / git restore | but discard <id> |
git cherry-pick | but pick |
gh pr create | but pr new <branch-name> -m "Title..." |
注意事項
- 読み取り専用の git の調査(
git log、git blame、git show --stat)は許可されています。 butがAGENT ACTION REQUIREDのスキル警告を表示した場合は、提案されたコマンドを一度実行してから、GitButler スキルを再読み込みして使用してください。警告が繰り返される場合は、再試行せずに報告してください。- コマンドの構文とフラグについては、
but skill referenceを参照してください。 - ワークスペースのモデルについては、
but skill conceptsを参照してください。 - ワークフローの例については、
but skill examplesを参照してください。