mcpField
I
inherit

inherit

github.com/camacho開発346 回インストール
リポジトリ

inherit について

inheritは、親ブランチの更新を現在のブランチにマージする開発スキルです。依存ブランチへの順次適用にも対応し、競合時は処理を止めてユーザーに解決を委ねます。

主な機能

  1. 01親ブランチの検出または指定
  2. 02親から現在のブランチへのマージ
  3. 03依存ブランチへの順次適用
  4. 04プッシュの省略
  5. 05競合時の停止と報告

活用シーン

  1. 01mainの更新を現在のブランチに反映
  2. 02依存するブランチ群の更新
  3. 03プッシュせずにローカルでマージ

インストール

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

$npx skills add https://github.com/camacho/ai-skills --skill inherit

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

詳細

inherit

メンタルモデル:「私は子です。親が持っているものを受け取りたいです。」

現在のブランチを(必要に応じてその子孫も)親ブランチの最新状態にします。これは /ship(ターゲットへの送信)と /isolate(親から新しい子ブランチをフォーク)の対になる、取り込み用のコマンドです。

使用するタイミング

  • 現在のブランチがベースブランチより古くなっている場合。
  • 依存関係のあるブランチのスタックに、親の最新コミットを順に反映する必要がある場合。
  • wt、git-trim、gh が使えないウェブセッションや最小限の環境の場合。

変更を上流に送るために使わないでください — それには /ship を使います。新しいブランチの作成にも使わないでください — それには /isolate を使います。

なぜ rebase ではなく merge なのか

自律モードの git-rewrite-guard.sh は、git rebase、--amend、reset --hard、push --force* をブロックします。ベースから同期する際には、マージは並列ワークツリーのコミュニティ標準でもあります。破壊的な操作ではなく、ブランチスタックと組み合わせられ、強制プッシュが不要で、チェックアウトを共有していても安全です。このスキルでは常に git merge を使い、git rebase は使わないでください。

制約

  • Git のみを使用します。マージの手順では wt、git-trim、gh を使いません。ウェブサンドボックスでも動作します。
  • 状態を変更する操作では、必ず git -C <abs-path> を使います。Claude Code の Bash 呼び出し間で cd は維持されません。セッションの CWD から git を直接実行すると、プライマリワークツリーが対象になります。
  • コンフリクトを自動解決しないでください。コンフリクトの解決はユーザーが行います。

入力

フラグ目的
--stack依存ブランチを下から順にマージ
--parent <name>自動検出された親を上書き
--no-pushプッシュ手順を省略(コミットはローカルに残ります)

CI 停止時の処理:/ship と同じ規約を使います。ユーザーから CI が停止していると伝えられた場合は、各 git push を /local-merge に置き換えます。

手順

1. 現在のブランチとリポジトリのルートを解決する
REPO="$(git rev-parse --show-toplevel)"
CURRENT="$(git -C "$REPO" rev-parse --abbrev-ref HEAD)"

事前確認で中断する条件:

  • CURRENT が HEAD(デタッチ状態)の場合 → 「現在のブランチがありません。最初にブランチをチェックアウトしてください。」
  • 作業ツリーに未コミットの変更がある場合(git -C "$REPO" status --porcelain が空でない) → 「取り込む前に、ローカルの変更をコミットするか、スタッシュしてください。」
2. 親を検出する(--parent が指定されていない場合)
PARENT=$(git -C "$REPO" reflog show HEAD --pretty=format:'%gs' \
  | grep -m1 '^branch: Created from ' \
  | sed -E 's/^branch: Created from //; s|^origin/||')
PARENT="${PARENT:-main}"
  • grep -m1 は最新の「Created from」を取得します。これが実際のフォーク元です。
  • 先頭の origin/ を取り除き、ブランチ名の形式にそろえます。
  • reflog が空の場合(ウェブセッション、新規クローン、fetch で作成されたブランチ)は、main にフォールバックします。ユーザーにフォールバックであることを伝え、必要なら --parent で修正できるようにします。
  • 解決後に PARENT == CURRENT の場合 → 「すでに親ブランチにいます。取り込むものはありません。」

変更を加える前に、次のように表示します:Detected parent: <PARENT> (current: <CURRENT>). Inheriting from origin/<PARENT>.

3. 親をフェッチする
git -C "$REPO" fetch origin "$PARENT"

フェッチに失敗した場合(オフライン、ref が見つからない、origin 上で親が削除されている場合)は、エラーをそのまま表示します。別のブランチに黙って置き換えないでください。

4. 親を現在のブランチにマージする
git -C "$REPO" merge --no-edit "origin/$PARENT"

結果:

  • コンフリクトなし(通常のマージまたは早送り) → 続行します。
  • 変更なし(すでに最新) → その旨を明確に伝え、プッシュを省略します。
  • コンフリクトあり → 停止し、git status を表示して、コンフリクトしているパスを一覧表示し、制御をユーザーに戻します。自動解決を試みないでください。
5. スタックを順に処理する(--stack の場合のみ)

「依存ブランチ」とは、CURRENT を祖先に持つローカルブランチです。--stack の後に候補ブランチをユーザーが指定する(または名前を明示する)必要があります。黙って推測しないでください。ユーザーがブランチ名を指定していない場合は、一度だけ尋ねます。

順序:下から上へ、親を先に処理します。 2つずつ git merge-base --is-ancestor を使ってトポロジカル順序を見つけます。各手順で、残りのブランチのうち、ほかのどのブランチからも祖先とされていないものを選びます。そのブランチを次に処理します。

# B is downstream of A iff A is an ancestor of B
git -C "$REPO" merge-base --is-ancestor "$A" "$B"  # exit 0 = yes

この順序で各ブランチに対し、origin/main ではなく、チェーン内の直接の親(直前に処理したブランチ)をマージします。カスケードの目的は、親がすでに main を取り込んでおり、次に子が更新された親を取り込むことです。

PREV="$CURRENT"
for child in "${ordered[@]}"; do
  git -C "$REPO" checkout "$child"
  git -C "$REPO" merge --no-edit "$PREV"   # stop on conflict
  PREV="$child"
done
git -C "$REPO" checkout "$CURRENT"

コンフリクトが発生した場合は、カスケードを停止します。処理が止まったブランチと、コンフリクトしているパスを報告します。先のブランチに進まないでください。

6. プッシュ(または CI が停止している場合は /local-merge)

コミットを受け取った各ブランチ(CURRENT と、そこから派生したすべての子ブランチ)について:

git -C "$REPO" push origin "$BRANCH"

ユーザーから CI が停止しているとの合図があった場合は、ブランチごとに /local-merge を実行します。 --no-push が指定されている場合は、プッシュを完全にスキップし、公開待ちのローカルマージコミットが各ブランチにあることをユーザーに伝えます。 プッシュが拒否された場合(リモートに変更があった場合)は、強制プッシュしないでください。拒否されたことを報告し、/inherit を再実行するかどうかはユーザーに判断してもらいます。

7. 報告

段落ではなく、簡潔に要約します。

Inherited from <PARENT> into:
  - <CURRENT>   (merge <sha>, pushed)
  - <child-1>   (merge <sha>, pushed)

競合が発生した場合:

Inherit halted on <branch>: conflicts in <files>. Resolve, commit, then re-run /inherit.

クイックリファレンス

手順コマンド
親ブランチの検出git reflog show HEAD --pretty=format:'%gs' | grep -m1 '^branch: Created from'
フェッチgit -C "$REPO" fetch origin "$PARENT"
マージgit -C "$REPO" merge --no-edit "origin/$PARENT"
スタックの順序git merge-base --is-ancestor <a> <b> をペアごとにルートから実行
プッシュgit -C "$REPO" push origin <branch>
CI 停止時ブランチごとに /local-merge

失敗につながる考え方 — 明確に否定

正当化対処
「リベースのほうがすっきりするので、main にリベースしよう」禁止です。 自律モードでは書き換えガードによってブロックされます。マージを使用してください。
「reflog が空なので、ブランチ名のパターンから推測しよう」main にフォールバックします。ユーザーに伝えてください。命名から推測してはいけません。
「きれいにリベースしたあと、強制プッシュしよう」禁止です。 このスキルでは --force、--force-with-lease、--amend を使用できません。
「git pull --rebase を使おう」git rebase と同様に禁止されています。通常の git merge を使用してください。
「wt sync / git-trim を使おう」git のみを使用してください。これらのバイナリは Web セッションにはありません。
「スタックの順序は関係ないので、どの順番でもマージしよう」下から上へ(ルートに近いブランチから先に)マージし、各子ブランチが更新済みの親ブランチを取り込めるようにしてください。
「プッシュはスキップしよう」CI 停止時または --no-push が指定されている場合を除き、更新した各ブランチをプッシュしてください。
「競合? -X theirs で自動解決しよう」絶対にしないでください。 競合の解決はユーザーが行います。停止して報告してください。

危険な兆候 — 停止

  • git rebase、--amend、reset --hard、--force を入力しようとしている → 使用するスキルが違います。
  • 親ブランチの検出結果が空だったのに、main にフォールバックしていない。
  • スタックを上から下へ(親ブランチを最後に)マージしている → 順序を逆にしてください。
  • プライマリではないワークツリーで、セッションの CWD から -C を付けずに git を実行している。
  • git 操作以外でファイルを変更している — このスキルで実行できるのは git 操作のみです。

関連スキル

  • /isolate — 親ブランチから新しい子ブランチを作成します。
  • /inherit(このスキル)— 親から子へ取り込みます。受信方向。
  • /ship — 子から対象へプッシュします。送信方向。

ブランチの移動方向は 3 つです。分岐、下方向への同期、上方向への送信。

実行例

  • 「main をこのブランチに取り込んで」→ /inherit
  • 「スタックを main から更新して」→ /inherit --stack
  • 「ベースから同期するけど、まだプッシュしないで」→ /inherit --no-push
  • 「main ではなく develop に追いついて」→ /inherit --parent develop

コメント