3ブランチ運用(develop / pre / main)で git cherry-pick を繰り返していると、必ず事故ります。半年で4系統の事故パターンが見えたので、それを Claude Code skill として自動監査するツールを作りました。
PR #176 で実運用したところ、「両方の環境に既に反映済みなので NO-GO」 を正しく検出。確認工数が60%削減できました。
4系統の事故パターン
cherry-pick で過去に踏んだ事故を構造化すると、以下の4系統に整理できました。
1. 依存先行PR未反映
ターゲット環境に「依存している先行PR」が反映されていないのに cherry-pick すると、コンパイル/import が壊れます。
1develop: PR#100 (基盤) → PR#105 (新機能・PR#100依存)2pre: PR#100 未反映3→ pre に PR#105 だけ cherry-pick → import エラー2. スコープ拡張漏れ
「typo修正PR」と思って cherry-pick したら、実は同じファイルに別の重要修正が入っていた。一部だけコピーしようとして衝突 → 半端な状態でマージ。
3. 並行セッション先行反映
別セッションで先に cherry-pick されていることに気づかず、二重に当てて衝突。
4. target限定コミット衝突
「if env == 'pre' に限定したコード」を含むPRを main に持っていくと、pre 限定コードが本番で実行される事故。
skill 化の動機:人間チェックの限界
これらを毎回人間が目視で確認するのは無理でした。
- PR一覧を見る
- 依存関係を辿る
- target ブランチの履歴を確認
- 並行セッションの有無を確認
- スコープ範囲を比較
毎回30分かかり、しかも疲れているとミスります。
そこで 6項目の自動監査 を cherry-pick-audit skill として実装しました。
skill の6チェック項目
| # | チェック項目 | 判定基準 |
|---|---|---|
| 1 | 並行セッション検出 | ~/.claude/projects/.../*.jsonl の最終更新が30分以内 |
| 2 | Workspace整合性 | git status が clean、未push commitなし |
| 3 | 依存先行PR | PR本文の Depends on #NNN を抽出してtargetで存在確認 |
| 4 | スコープ拡張候補 | PR変更ファイルがtargetでも変更されているか |
| 5 | target限定コミット衝突 | コミットメッセージに [pre-only] [main-only] がないか |
| 6 | squashハッシュ整合性 | git log target --grep="(#NNN)" でtarget側に既反映でないか |
各項目で問題があれば 🔴 NO-GO、警告があれば 🟡 CONDITIONAL、すべてOKなら 🟢 GO を返します。
skill ファイル構成
Claude Code の skill は ~/.claude/skills/ 配下に配置します。
1~/.claude/skills/cherry-pick-audit/2├── SKILL.md # skill 定義(YAML frontmatter + 説明)3├── scripts/4│ ├── check_parallel_session.sh5│ ├── check_dependent_pr.sh6│ └── check_squash_match.sh7└── templates/8 └── audit_report.mdSKILL.md の冒頭は以下のような構造。
1---2name: cherry-pick-audit3description: cherry-pick 前監査。develop→pre→main で発生する4系統事故パターンを自動検出し、GO/NO-GO/CONDITIONAL を判定する4---5
6## 使い方7ユーザーが「PR#NNN を pre にcherry-pickしたい」と言ったら、このskillを呼び出す。8
9## 6項目チェック101. 並行セッション検出112. ...skill のキモは、Claudeが「いつ呼び出すべきか」を理解できる description を書くことです。
実運用ログ:PR#176 で NO-GO を正しく検出
ある日、6本のPR(#157〜#162)を pre リリースする計画がありました。MEMORY.md には「未反映、第1陣6本推奨」と書いてあったため、それを信じて作業開始したかったところ。
skill を起動すると、以下のレポートが返ってきました。
1🔴 NO-GO(pre/main両方とも既に反映済み)2
3Check 6: squashハッシュ整合性4 - PR#157 (#157) → pre に既存(commit abc1234)5 - PR#159 (#159) → pre に既存(commit def5678)6 - PR#160 (#160) → main に既存(commit 9abc012)7 - ...8
9理由: MEMORY.md のサマリ行と実際のgit履歴が乖離している10推奨: cherry-pick を中止し、MEMORY.md を更新することMEMORY.md の1行サマリが誤誘導の起点になっていたわけです。skill が実機 git log で確認することで、無駄な cherry-pick 衝突解決の30分を節約できました。
設計時のトレードオフ
スピード vs 精度
すべての項目を厳密にチェックするとskill実行が遅くなります。実用上は以下のバランスにしました。
- Check 1(並行セッション): 1秒以内
- Check 6(squashハッシュ): 30コミット以内のスキャンで5秒以内
- Check 3(依存PR): GitHub API呼び出しなしで本文grepのみ → 不完全だが高速
False Positive を許容する
「CONDITIONAL」を多めに返す設計にしました。NO-GOを乱発するとskillが信用されなくなります。CONDITIONAL = 「人間判断を仰ぐ」と割り切ります。
skill 自体のテスト
過去の実事故ケース8件を再現テストとして残しました。skill 改修時はこの8件で必ずパスすることを確認します。
効果測定
導入後1ヶ月のデータです。
| 指標 | Before | After |
|---|---|---|
| cherry-pick 1回の確認時間 | 30分 | 12分 |
| 事故再発件数 | 月3件 | 月0件 |
| skill 自身の誤判定 | - | 月1件(CONDITIONAL→人間判断OK) |
確認時間60%削減、事故ゼロ。「過去の失敗を skill 化する」は強力だと実感しました。
まとめ
- cherry-pick 事故は4系統に分類できる(依存先行 / スコープ / 並行 / target限定)
- 6項目を機械的にチェックする
cherry-pick-auditskill を実装 - MEMORY.md と実態の乖離も検出できた
- 確認工数60%削減、事故ゼロ
「同じ事故を3回したら skill 化する」は、AI駆動開発の効率化原則として強くおすすめできます。