mcpField
S
splitting-pr

splitting-pr

github.com/satanlittlehelper開発041 回インストール1 日前に更新
リポジトリ

splitting-pr について

splitting-pr は、大きな未コミット差分をレビューしやすい積み重ね型の PR に分ける開発者向けスキルです。ファイルの割り当てと進捗をセッション間で記録し、ファイルの欠落を防ぎます。

主な機能

  1. 01差分を積み重ね型 PR に分割
  2. 02状態ファイルで進捗を追跡
  3. 03未完了の分割を別セッションで再開
  4. 04パスと拡張子でファイルを分類
  5. 05バックアップブランチに元の差分を保存

活用シーン

  1. 01大きなブランチ差分をレビューしやすい PR に分割
  2. 02複数 PR の分割作業を中断・再開
  3. 03密接に関連するファイルを同じ単位にまとめる

インストール

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

$npx skills add https://github.com/satanlittlehelper/ai-dev-kit --skill splitting-pr

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

同梱ファイルreferences/block-cycle.mdreferences/resuming.md

詳細

PR の分割

概要

1 つのブランチに大きな未コミットの差分があると、レビューのリスクが高い大規模な PR が 1 つできてしまいます。このスキルでは、小さな PR を積み重ねたチェーンに分割します。各 PR はレビューしやすい規模(ビジネスロジックのファイルが 15 個以下。アセットとドキュメントは除外)にし、どのファイルをどこに割り当てたかを見失わずに、セッションをまたいで分割を中断・再開できるよう、状態ファイルで追跡します。このスキルは独自のビルド/リンター/テストを実行しません。検証は、git push 時にプロジェクト独自の pre-push フックが行う内容に委ねます(references/block-cycle.md のステップ 6)。そのフックがプッシュを拒否した場合、ブロックの分け方が適切でなかったという合図であり、このスキルが事前に確認するものではありません。

このスキルは事後的にのみ動作し、差分が存在する前に分割を計画することはありません。スキルの呼び出し時に大きな未コミットの差分がなければ、そのことを伝えて終了してください。分割するものがまだありません。

このスキルはエントリーポイントであり、保存先/命名/状態ファイルの規約(以下。両方のリファレンスで共通)を管理し、該当する手順に案内します。

状況読むもの
現在のブランチに .claude/pr-split/<slug>-state.json がまだ存在しない、またはユーザーが新しい分割を始めるreferences/block-cycle.md の「初回の呼び出しのみ:バックアップを作成し、その後ベースラインを確立する」セクションから読む
現在のブランチに未完了のブロックがある .claude/pr-split/<slug>-state.json がすでに存在する(新しいセッション、または作業の再開)references/resuming.md

状況に応じて該当するリファレンスのみを読んでください。どちらも、このファイルの保存先/スキーマ/分類規約を共通の前提としているため、リファレンスごとに改めて導き出す必要はありません。

承認ゲート

references/block-cycle.md でユーザーによる承認、却下、編集が必要な各項目(ブロックのファイル分け、コミットメッセージ、PR のタイトル/本文、Plannotator によるレビュー結果)は、具体的な選択肢(例:「承認」/「グループ分けを変更」、「承認」/「メッセージを編集」)を示して AskUserQuestion で尋ねてください。チャットにテキストを投稿して自由形式の返信を待つ方法は使いません。これにより、ユーザーは何かを入力しなくてもクリックで承認できます。例外は、選択肢が固定されていない実際のデータ入力に限ります。たとえば Forgejo も gh も使えない場合に、手動で作成した PR の URL を貼り付けるケース(references/block-cycle.md のステップ 6)は、選ぶ項目がないため通常のチャットプロンプトのままにします。

ファイルの分類

拡張子/パスに基づくヒューリスティックを使います。ファイルの内容から推測してはいけません。

  • アセット/ドキュメント(15 ファイルの上限から除外): *.md、*.mdx、README*、CHANGELOG*、画像、フォント、その他の静的ファイル(.svg .png .jpg .jpeg .gif .webp .ico .woff .woff2 .ttf .eot .pdf)、ロケールファイル(.po、.pot)。
  • ビジネスロジック(上限に算入): その他すべて。あらゆる言語のソースファイル、設定ファイル/テストファイル(.json、.yaml、.yml など)は常にロジックとして数えます。意味上の役割を推測して分類し直してはいけません。

グループ分けの優先順位

ブロックへのグループ分けは、差分を読んで判断するこのスキル独自の判断です(インポート、シンボルの使用、ドメイン上の関連性)。固定的なアルゴリズムに従うものではありません。**密接に関連するファイルをまとめることは、常に 15 ファイルの上限より優先されます。**密接に結合したファイル群を分割すると、一方の半分が、もう一方の半分でまだ導入されていないものを参照してしまう場合、そのブロックに限り上限を超えて構いません。その場合は、ユーザーに提示するブロック案で明示し、その点について確認を得てから先に進んでください。これを実証的に確認するためのローカルなビルド/リンター/テスト実行はありません。実際の確認は、git push 時にプロジェクト独自の pre-push フックが行います(references/block-cycle.md のステップ 6)。プッシュが拒否された場合は、グループ分けをやり直す合図です。

ストレージ

  • 状態ファイル:.claude/pr-split/<slug>-state.json。<slug> は元のソースブランチ名(分割を開始したブランチ名)で、/ を - に置き換えたものです。
  • 未追跡です。 git add されることも、コミットされることも、ブロックの差分や PR に含まれることもありません。作業ツリー内にのみ存在し、同じチェックアウト内でブランチを切り替えても保持されます(未追跡ファイルは、競合しない限り git checkout <branch> の影響を受けません)。ただし、プッシュもバックアップもされません。
  • 分割の完了時に自動的に削除されます(詳細は「完了」を参照)。これは進行中の分割のワークフロー状態であり、永続的な記録ではありません。最後のブロックの PR 作成後もこのファイルが残ることを前提としているものは、リポジトリ内にありません。
  • バックアップブランチ: <sourceBranch>_backup — 元の差分全体を保持する通常のコミットを 1 つ含むブランチです。他の処理が元の差分に触れる前に作成されます(references/block-cycle.md のステップ 0)。これは、分割中に後続の処理で問題が発生した場合にデータ損失を防ぐ保証となります。状態ファイルとは異なり、このスキルの自動処理が削除することはありません。削除するか保持するかは、分割自体の完了時期とは無関係に、人間が安全策として判断します。

完了

blocks 内のすべてのブロックが status: "pr-created" になり、unassignedFiles が空になると、分割は完了です。その時点で、ワークフローの最後の処理として .claude/pr-split/<slug>-state.json を削除します。このファイルの役割は分割の進行中に進捗を追跡することであり、すべてのブロックの PR が作成された後は、state.json で追跡するものは残っていません。

削除する前に、state.json から最終サマリーを読み取ってユーザーに表示してください(そのため、削除より先に表示する必要があります)。これにより、一連の情報をそのままレビュー用に転送できます。

  1. ブロック順にすべての PR を列挙し、それぞれ N. <prTitle> — <prUrl> の形式で記載します。
  2. スタックを表す表を作成します。列は | # | PR | Head branch | Base branch | とし、ブロックごとに 1 行を記載します。branch を head、baseBranch を base とします(ブロック 1 は元の base を対象とし、後続の各ブロックは直前のブロックのブランチを対象とします)。

その後、分割が完了したことをユーザーに伝えます。 これはバックアップブランチ <sourceBranch>_backup(上記の「ストレージ」を参照)とは無関係です。このスキルの自動処理は、完了状況にかかわらずバックアップブランチを削除しません。

状態ファイルの編集

.claude/pr-split/<slug>-state.json はプレーンテキストファイルです。リポジトリ内の他のファイルと同様に、Read/Edit ツールで読み取り、編集してください。シェルのワンライナー(jq、python -c、node -e など)は使用しないでください。このファイルは小さく、ブロックの追加、status の変更、unassignedFiles とブロックの files 間での少数のパスの移動など、このスキルで行う書き込みはすべて、直接確認できるテキスト編集で済みます。間に JSON 処理ツールを使う必要はありません。

State File Schema

{
  "sourceBranch": "feature-x",
  "baseBranch": "main",
  "createdAt": "2026-09-08T12:00:00Z",
  "updatedAt": "2026-09-08T12:00:00Z",
  "totalFiles": { "logic": 42, "assets": 7 },
  "originalFiles": ["src/a.ts", "src/z.ts", "README.md"],
  "blocks": [
    {
      "index": 1,
      "branch": "feature-x",
      "baseBranch": "main",
      "files": { "logic": ["src/a.ts"], "assets": ["README.md"] },
      "status": "approved",
      "commitSha": null,
      "prUrl": null,
      "prTitle": null
    }
  ],
  "unassignedFiles": ["src/z.ts"]
}
  • originalFiles は、分割開始時(ブロックがまだ存在しない時点)に一度だけ取得され、その後再取得されることのない、元の差分に含まれる完全なファイル一覧です。これは「何も失われない」不変条件の検証に使われる、永続的な正解データです。詳しくは以下を参照してください。ブロック 1 の branch は名前を変更した新しいブランチではなく、ソースブランチそのもの(sourceBranch)です。これは以下の「ブランチと PR の戦略」と一致します。
  • status は次の順序で進み、前の状態に戻ることはありません。planned → approved → committed → review-passed → pr-created。自動で closed になるステータスはありません。詳しくは上記の「完了」を参照してください。ブロックは提案時(block-cycle.md のステップ 1、ユーザーの承認前)に "planned" として記録され、ユーザーの承認後(ステップ 3)に "approved" に切り替わります。これが "planned" ブロックのファイルに対して意味することについては、以下の不変条件の例外を参照してください。
  • unassignedFiles には、元の差分に含まれるファイルのうち、まだどのブロックにも割り当てられていないものをすべて記載します。"planned" ブロックの提案ファイルも、引き続きここに記載されます。詳しくは以下を参照してください。
  • 何も失われない不変条件。このファイルへの書き込みごとに、目視確認だけでなく機械的に検証します。"approved" 以降のステータスを持つすべてのブロックについて、各ブロックの files.logic と files.assets の和集合に unassignedFiles を加えたものが、originalFiles と完全に一致しなければなりません(ファイルの欠落や、ブロック間での重複がないこと)。例外: status: "planned" のブロックはこの和集合から除外されます。提案されたファイルは、承認されて status が "approved" に切り替わるまで、unassignedFiles によってのみ数えられます(その時点で block-cycle.md のステップ 3 が同じ書き込み内で該当ファイルを unassignedFiles から削除するため、どの段階でも不変条件が保たれます)。originalFiles は分割開始時に、リネームやスペースを安全に処理できる単一のコマンド(ヌル区切りで出力し、適切に解析する git status --porcelain=v1 -z。リネームやスペースを含むパスを壊す awk '{print $2}' は使わない)で一度だけ取得し、その後は作業ツリーから再取得しません。すでにコミットされたファイルは未コミットの変更として表示されなくなるため、再取得すると検証対象からひそかに消えてしまうからです。(上記の例外に従って)和集合が一致しない場合、つまりファイルが 2 つのブロックに現れる場合や、originalFiles 内のファイルがブロックにも unassignedFiles にもない場合は、ほかの作業を行う前に停止し、不一致をユーザーに伝えてください。不変条件を満たすために、ファイルをひそかに削除したり重複させたりしてはいけません。

ブランチと PR の戦略

  • 現在のブランチがブロック 1 になります。名前は変更しません。ブロック 1 のコミットはそのブランチに直接追加されます。その PR のターゲットは通常そのブランチがターゲットとする先であり、状態ファイルの baseBranch に記録します。既存の PR や追跡ブランチから明らかでない場合は、ユーザーに確認してください。
  • ブロック N+1 は、ブロック N 自身のコミットが存在する状態になった後、そのブランチから派生し、<sourceBranch>-<N+1> という名前を付けます(例:feature-x-2、feature-x-3 など)。その PR のベースはブロック N のブランチです。これは、すべてを main をベースにするのではなく、積み重ねたブランチの連鎖です。マージ済みブロックの PR のベースを main に戻す作業はユーザーに委ねられ、自動化の対象外です。
  • PR の作成では、最初に一致した方法を使用します。(1)環境に FORGEJO_TOKEN が設定されている場合は、Forgejo API(origin URL からホストとリポジトリを特定し、POST /api/v1/repos/<owner>/<repo>/pulls を実行)経由で PR を作成します。(2)gh がインストールされており、リモートが GitHub の場合は、gh pr create を実行します。(3)それ以外の場合は、ブランチをプッシュしてユーザーに手動で PR を開くよう依頼します。その後、ユーザーが PR の URL を貼り付けるまで待ってから記録し、次に進みます。PR の作成がひそかに省略されることはありません。詳しくは references/block-cycle.md のステップ 6 を参照してください。

よくある間違い

間違い修正方法
15 ファイルの上限を絶対的なものとして扱い、上限を守るために密接に関連するファイルを分割する関連性を優先します。そのブロックでは上限を超え、そのことを明示して、明確な確認を得てください
.json/.yaml 設定ファイルを「実際にはロジックではない」と分類する常にビジネスロジックとして扱います。分類は拡張子のみに基づいて行い、内容に基づいて行わないでください
.claude/pr-split/<slug>-state.json をコミットまたは git add する常に未追跡のままにしてください
ブロックをコミットする前に、ローカルでビルド/lint/テストを実行するこのスキルの対象外です。検証には、git push 時に実行されるプロジェクト独自のプッシュ前フックを使用します
すべてのブロックの PR のベースを main にする元のベースをターゲットにするのはブロック 1 のみです。それ以降の各ブロックの PR のベースには、直前のブロックのブランチを指定します
何も失われていないという不変条件が満たされていないのに、黙って処理を続行する停止して不一致を明らかにしてください。帳尻を合わせるためにファイルを自動的に除外したり、重複させたりしないでください
バックアップブランチを作成せずに分割を開始する、またはワークフローの一環として <sourceBranch>_backup を削除するreferences/block-cycle.md のステップ 0 を必ず最初に実行します。その後、このスキルの自動処理ではバックアップブランチに触れないでください
最後のブロックが pr-created に達した後も、.claude/pr-split/<slug>-state.json をディスクに残しておくunassignedFiles が空になったら、最後のアクションとして削除してください。「完了」を参照してください

コメント