mcpField
G
gh-pr

gh-pr

github.com/dzhuneyt開発063 回インストール3 週間前に更新
リポジトリ

gh-pr について

gh-prは、現在のブランチからGitHubのプルリクエストを作成し、変更全体に基づくタイトルと本文を用意するスキルです。`gh`を使い、プッシュ前にリポジトリ、ブランチ、ローカル作業の状態を確認します。

主な機能

  1. 01リポジトリとブランチの事前確認
  2. 02ベースブランチとローカル変更の評価
  3. 03既存PRとブランチ上の作業競合の検出
  4. 04強制プッシュを使わない送信
  5. 05変更内容に基づくPRタイトルと本文の作成

活用シーン

  1. 01完了したブランチからプルリクエストを作成
  2. 02プッシュ前に無関係なローカル作業を特定

インストール

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

$npx skills add https://github.com/dzhuneyt/skills --skill gh-pr

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

詳細

gh-pr

現在のブランチから、直近のコミットメッセージだけではなく、実際の変更内容を反映したタイトルと本文でプルリクエストを作成します。目標は、レビュアーが先に差分を読まなくても理解できる PR にすることです。

すべての操作に gh を使用してください。認証と API を処理し、最後に URL を返します。API を直接呼び出すスクリプトは作成しないでください。

作業の流れ

順番に進める 3 つのフェーズがあります。この順序を決める重要なルールは、正しいブランチに作業があると確認できるまでは、何もプッシュしないことです。フェーズ 2 はすべてローカルで完結し、取り消し可能です。最初の、いわば不可逆な操作(プッシュ)はフェーズ 3 の冒頭です。

  Phase 1  Can I run?         local gates + gh auth
                              any gate fails -> stop
     |
     v
  Phase 2  Right place?       base -> assess -> branch-fit -> settle tree
                              all local, nothing pushed yet
     |
     v
  Phase 3  Open the PR        push -> compose -> gh pr create -> url

フェーズ 1 · 実行できるか

ステップ 0:簡易ローカルゲート

すべてローカルで実行され、ネットワークもプッシュも不要です。そのため、時間のかかる処理を始める前に、ミリ秒単位で失敗を検出できます。順序が重要です。最も簡単で、最も基本的なチェックから行います。

即時終了条件 — 後続の処理では回復できないため、明確なメッセージを表示して直ちに終了します。

  1. Git リポジトリではない。 git rev-parse --is-inside-work-tree を実行します。最も速いチェックなので、最初に実行してください。
  2. gh がインストールされていない。 command -v gh を実行します。認証チェックのうち、ローカルで簡単に行える部分です。gh auth status(ネットワークを使用します。プリフライトを参照)とは分けてください。「インストールされていない」と「ログインしていない」では、異なるメッセージが必要です。
  3. origin リモートがない。 git remote get-url origin を実行します(終了コードが 0 以外の場合は origin がありません)。このスキルは、origin という名前の単一のリモートを前提とし、そこにブランチをプッシュします。origin がなければ、プッシュ先も gh の対象もないため、ここで終了してください。フォークを使うワークフローは対象外です。フォークにプッシュしながら、upstream リポジトリに対して PR を作成する方法(--head owner:branch)は意図的に扱いません。リモートの名前が upstream など別の名前しかない場合は、推測せずに停止して確認してください。
  4. リモートが GitHub ではない。 git remote get-url origin を実行し、ホストを確認します。GitLab、Bitbucket、その他の場合、gh では対応できないため、ここで終了してください。
  5. HEAD が分離している、またはブランチが未作成。 git symbolic-ref -q HEAD を実行します(出力が空の場合は分離状態です。コミットのない新しいリポジトリも検出します)。ブランチがなければ、PR を作成できません。

確認して停止 — 実行は可能ですが、ほとんどの場合は誤りなので拒否せず、一時停止します。

  1. デフォルトブランチ上にいる。 main から main への PR は、ほとんどの場合、誤りです。簡易チェックでは、git symbolic-ref refs/remotes/origin/HEAD がローカルで解決できる場合(クローン時に origin/HEAD が設定された場合にのみ存在します。たとえば git remote set-head origin -a を実行した場合)、ここで比較します。存在しない場合は、ここではチェックを省略してください。プリフライトでデフォルトブランチを正式に解決し、再確認します。
  2. 操作の途中である。 MERGE_HEAD、.git/rebase-merge、.git/rebase-apply、.git/CHERRY_PICK_HEAD、.git/REVERT_HEAD を確認します。リベース、マージ、チェリーピック、またはリバートの途中では、ツリーが中途半端に適用された状態です。この時点で PR を作成しても役に立ちません。
  3. ベースより先のコミットが 0 件。 これは簡易テストにすぎません。ベースはまだ解決されていません(フェーズ 2 で解決します)。ローカルで解決済みのデフォルトブランチ(ステップ 0 のデフォルトブランチチェックで得た origin/HEAD の参照先。参照がない場合は省略)と比較するには、git rev-list --count origin/<default>..HEAD を使用します。コミットが 0 件でも終了する前に、git status --porcelain を確認してください。作業ツリーに変更がある場合、作業は存在しますが未コミットです。終了せずにフェーズ 2 に進み、「未コミットの変更を整理する」でコミットしてください。コミットが 0 件で、かつ作業ツリーがクリーンな場合のみ、即時終了します。フェーズ 2 では、ユーザー指定のベースを含めてベースを正式に決定し、このチェックに優先します。ここでコミット数が 0 以外でも、実際のベースに対してコミットがある保証にはなりません。また、origin/<default> がローカルで古くなっている可能性もあります。

ステップ 0 を通過したら、git branch --show-current で、以降の処理に使用するヘッドブランチを取得します。

事前確認(ネットワーク)

往復通信が発生するため、Step 0 が問題なく完了した後にのみ実行します。

  • gh auth status — CLI が認証済みであることを確認します。認証されていない場合は、ユーザーに gh auth login を案内します。代わりにログインしてはいけません。

  • ここでデフォルトブランチを一度だけ特定します。 以降のすべて(Step 0 のデフォルトブランチ確認と、Phase 2 のベース)は、この単一の値を参照します。フォールバックの順序 — 最初に見つかった値を使用します。

    1. git symbolic-ref --short refs/remotes/origin/HEAD → origin/ のプレフィックスを削除します(ローカルで実行するため、往復通信は発生しません)。
    2. gh repo view --json defaultBranchRef --jq .defaultBranchRef.name(信頼できる値を取得するため、往復通信が1回発生します)。

    origin/HEAD が存在せず、Step 0 のローカル確認をスキップした場合は、現在のブランチがこのデフォルトブランチではないことを確認したうえで、ここで再確認します。


PHASE 2 · 作業場所は適切ですか?

このフェーズで行う処理はすべてローカルです。プッシュする前に、すべてを確認してください。

ベースブランチを決定する

Preflight ですでに特定したデフォルトブランチを再利用します。もう一度特定してはいけません。ユーザーが別のベースを指定していない限り、このデフォルトを使用します。スタックされた PR(別のフィーチャーブランチを対象とするフィーチャーブランチ)は実在しますが、まれです。通常、ユーザーはその旨を伝えます。判断に迷う場合は、main と決めつけず、確認してください。

ローカルの状態を確認する

情報を一度だけ収集します。これは、ブランチ適合性の判断と PR 本文の両方で使用します。

まず、アップストリームを一度だけ特定します。デフォルトの初回 PR の場合、アップストリームはありません。ブランチはまだプッシュされていないため、origin/<branch> は存在せず、origin/<branch>..HEAD の比較はエラーになります。

git rev-parse --abbrev-ref @{u} 2>/dev/null               # upstream, or empty
  • アップストリームが存在する場合 → 未プッシュのコミットは git log --oneline @{u}..HEAD です。
  • アップストリームがない場合(初回 PR)→ 比較対象がないため、ベース以降のすべてのコミットを未プッシュとして扱い、origin/<branch> との比較は完全にスキップします。
git status --porcelain                                    # dirty tree?
git log --reverse --format='%s%n%b' origin/<base>..HEAD   # commits since base
git diff --stat origin/<base>...HEAD                      # files + scope
gh pr list --head <branch> --state open --json number,url,title  # open PR?

ローカルのみの差分 = 未プッシュのコミット + 未コミットの変更です。これはまだどこにも反映されていない作業であり、ブランチ適合性の確認で判断する対象です。初回 PR の場合、ベース以降のすべてのコミットがこの差分に含まれます。

ブランチ適合性の判断

想定される失敗パターン:ユーザーがフィーチャー A を完了し(すでに PR を作成している場合もあります)、ブランチを切り替えずにフィーチャー B に着手し、B の作業を A にプッシュしようとしている状態です。

「ブランチ名が差分と一致するか」を判断基準にしてはいけません。汎用的な名前や個人的な名前(dev、wip、dzh/misc)は何にも一致せず、誤検知が頻発します。また、ブランチのスコープが正当に広がることもあります。すでにそのブランチに PR があるか、さらにその上にローカルのみの作業があるかを判断基準にします。

  open PR on branch?   local-only delta?   -> action
  -----------------------------------------------------------------
  no                   either                 open a fresh PR
  yes                  none                   nothing new -> stop
  yes                  some                   STOP and ask (below)

通常のフローを止めるのは最後の行だけです。その場合は、差分のみ(ブランチ全体ではなく)を要約します。たとえば、「ブランチ <branch> にはすでにオープンな PR #123 があります。それ以降、未プッシュのコミットが 2 件、変更されたファイルが 4 つあります。これらはこのブランチに含めますか。それとも独自のブランチに移しますか?」

この確認は高い精度を保ってください。「本当に正しいブランチにいますか?」と日常的な PR を中断するようでは、ユーザーは確認を読み飛ばすようになり、役に立たなくなります。フローを止めるのは右下のセルだけです。

作業を移す必要がある場合

コミット済みか未コミットかで、手順とリスクが大きく異なるため、対処方法を分けます。

  move the work off this branch:

  uncommitted  ->  git switch -c <new> origin/<base>      safe, just do it
                   (then continue — PR opens from <new>)
  committed    ->  git switch -c <new> origin/<base>      you do this
                   cherry-pick the stray commits onto <new>
                   ...then reset old branch + force-push   user's call — STOP

コミット済みの場合、意図的に古いブランチには手を加えずに止めます。紛れ込んだコミットを取り除くには履歴の書き換えが必要で、それには強制プッシュが必要になります。このスキルは自動で強制プッシュを行いません。特に、すでにオープンな PR があるブランチでは決して行いません。手順 1~2 を実行してから、履歴の書き換えはユーザーに委ねます。

どちらの方法でも重要なのは、現在の先端ではなく origin/<base> から分岐することです。現在の場所から git switch -c <new> を実行すると、新しいブランチは古いブランチの上に作成され、その PR に古いブランチのすべてのコミットが含まれてしまいます。

未コミットの変更を整理する

作業対象が正しいブランチになったら、次のようにします。

git status --porcelain

作業ツリーに変更がある場合は、ファイルを提示して停止してください。 ユーザーに代わってコミットしてはいけません。ユーザーはまだ考えをまとめている途中かもしれず、黙ってコミットすると、ユーザー自身が判断したかった変更が埋もれてしまいます。コミットするか、スタッシュするか、そのまま残すかを尋ねてください。コミットを依頼された場合は、Conventional Commit(フェーズ 3 を参照)の形式でメッセージを書いてください。種類は、ひと律に chore とせず、変更内容に基づいて選んでください。


フェーズ 3 · PR を作成する

ブランチをプッシュする

git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null
  • アップストリームがない場合 → git push -u origin <branch>。
  • アップストリームがあり、ローカルが先行している場合 → git push。
  • --force や --force-with-lease は絶対に使わないでください。プッシュが拒否された場合は、その旨を報告してユーザーの判断に任せてください。

タイトルと本文を作成する

任意:本文を書く前にベースブランチを更新してください。 git fetch origin <base> を実行して origin/<base> を更新すると、フェーズ 2 の差分コマンド(git diff --stat origin/<base>...HEAD、git log ... origin/<base>..HEAD)で、古くなっている可能性のあるローカルコピーではなく、実際のマージベースを確認できます。最後にフェッチしてからベースブランチが更新されている可能性がある場合(マージ、リベース、またはチームメンバーが活発に作業している共有ブランチなど)に実行してください。速度を優先する場合や、ベースブランチが最新だと分かっている場合(例:直前にプルした場合)は省略してください。ネットワークへの往復が 1 回発生します。

まず、プロジェクトの慣習を確認してください。

  • PR テンプレート — GitHub は優先順位に従い、ルートにある 3 つの場所(.github/、docs/、リポジトリのルート)からテンプレートを見つけます。各場所で pull_request_template.md、PULL_REQUEST_TEMPLATE.md、または PULL_REQUEST_TEMPLATE/ ディレクトリを探してください。候補は次のとおりです:.github/pull_request_template.md、.github/PULL_REQUEST_TEMPLATE.md、.github/PULL_REQUEST_TEMPLATE/、docs/pull_request_template.md、docs/PULL_REQUEST_TEMPLATE.md、docs/PULL_REQUEST_TEMPLATE/、pull_request_template.md、PULL_REQUEST_TEMPLATE.md、PULL_REQUEST_TEMPLATE/。存在する場合は、独自の構成を考えるのではなく、テンプレートの各セクションを埋めてください。メンテナーがその構成を選んだのには理由があります。
  • 関連する issue — ブランチ名とコミットを調べてください。
    • #123 / fixes #123 のような GitHub issue。
    • eng-412 のような Linear キー。ブランチ名(dzh/eng-412-token-refresh など)によく含まれます。Linear は、タイトルまたは本文にキーを含む PR を自動で関連付けるため、どちらかにキーを含めてください。
    • ブランチが issue に明らかに対応しているにもかかわらず、クローズキーワードがない場合は、変更が一部しか対応していない場合を除き、Closes #123 / Fixes ENG-412 のようなキーワードを追加してください。

タイトル: 変更全体を説明する、命令形の 1 行にしてください。ブランチに 5 つのコミットがある場合は、5 番目のコミットだけでなく、すべてを要約してください。デフォルトでは Conventional Commit 形式を使いますが、明確なリポジトリの慣習がある場合(commitlint の設定や、一貫性のある既存の PR/コミットタイトルなど)は、それに合わせてください。確立されたリポジトリのスタイルに Conventional Commit を無理に当てはめると、commitlint やスカッシュマージのツールと衝突することがあります。種類とスコープは、変更全体を反映させてください。

Conventional Commit 形式

PR タイトルと、このスキルが作成するすべてのコミットに使用します。

type(optional-scope): short imperative description
  • タイプ: feat、fix、docs、style、refactor、perf、test、build、ci、chore、revert。内容に最も合う具体的なタイプを選び、安易に chore を選ばないでください。
  • スコープは省略可能ですが、指定すると便利です。変更したパッケージ/モジュール/領域を指定します。例:feat(auth):。
  • 説明は小文字で、命令形にし、末尾にピリオドを付けず、約72文字以内にします。
  • 破壊的変更: タイプ/スコープの後に ! を付けます(feat(api)!: ...)。コミットには BREAKING CHANGE: フッターを追加します。

変更が複数のタイプにまたがる場合は、複合タイプを作らず、主なタイプを選びます。

本文(テンプレートがない場合)— 短く、ざっと読める内容にします。

## What
<one or two sentences: which files, what kind of change>

## Why
<one or two sentences: what made this necessary>

## Notes for review
<the contestable parts only>

<Closes #N / Fixes ENG-N if applicable>

約300語以内に収め、表は最大1つにしてください。それを超えると、ほとんどの場合、内容の言い換えになってしまいます。

「レビュー時の注意点」セクションは、内容が脱線しがちです。差分の要約ではありません。差分はそこにあります。レビュー担当者が異議を唱える可能性のある点を短く列挙します。たとえば、導き出した推論、判断に迷った箇所、主張している数値、このブランチで以前に誤っていた点などです。該当するものがなければ、このセクションは省略してください。

短くまとめるためのルール:

  • 最も重要な指摘を1つ、最初に述べる。 レビュー担当者が見落としてはいけない唯一の点を太字で冒頭に記載します。ほかの内容はすべて、その指摘を補足するものです。同じ重みの太字ブロックが3つあるなら、何が重要かを決められていません。
  • 影響は1度だけ述べる。 箇条書きですでに指摘の意味を説明しているなら、その意味をさらに説明する段落は追加しません。
  • 成果物を指し示し、内容をコピーしない。 差分に詳細がすべて含まれている場合は、簡潔にして「記録に全表があります」と記載します。本文は読む順番を示すものであり、差分の複製ではありません。
  • 表の行は異なる動作を示すものであり、実行したコマンドの違いを示すものではありません。 同じ結果と原因に該当する行はまとめます。検証を8回実行して4つの動作が確認された場合、表は4行にします。
  • レビュー担当者が何かが壊れたと思い込む可能性がない限り、否定的な結果は削除します。
  • 本文の範囲を差分に合わせる。 変更が扱っていないものの、変更によって浮上した未解決の質問は、ここではなく課題として記録します。

有用性を保つためのルールです。文字数を減らすために、以下を省略してはいけません。

  • このブランチで以前に誤っていた点と、修正した内容。
  • 置き換えられた判断が当時は正しかった理由。「XはYではないと記録されており、マージ時点では正しかった。その後Yが反映された」は、調査すべきエラーではなく、状況の変化として伝わります。
  • 正確な識別子:ポリシーID、エラー文字列、バージョン、フラグ。これらはレビュー担当者が確認すべき箇所を示します。

余計な内容を加えないでください。

Draft と ready

デフォルトではレビュー準備完了とします。ブランチが未完成に見える場合(コミットの件名に wip、tmp、fixup!、squash! が含まれる場合)は、自動的に --draft に切り替えます。ユーザーから明示的な依頼がある場合(例:$ARGUMENTS に「draft」が渡された場合)は、必ずそれに従ってください。

Open

gh pr create \
  --base <base> \
  --head <branch> \
  --title "<title>" \
  --body "<body>" \
  [--draft]

依頼されていない限り、レビュー担当者、担当者、ラベル、マイルストーンを追加しないでください。自動割り当ては相手に通知を乱発し、自動ラベル付けは、管理権限のない分類体系を推測することになります。

gh pr create がPRはすでに存在すると報告した場合、2つ目のPRを作成せず、既存のURLを提示して、更新するか(gh pr edit)確認してください。(通常、フェーズ2で先に確認します。)

Finish

PRのURLだけを1行で出力します。ユーザーが求めているのはそれです。差分を要約して返さないでください。ユーザー自身が作成した内容だからです。

次の行に、自動マージのヒントを1行で出力します:enable auto-merge: gh pr merge <number> --auto --squash(PR番号を置き換え、リポジトリで使われているマージ方法(--squash、--merge、--rebase)を選択します)。このスキルはこのコマンドを実行しません。ユーザーが明示的に選択できるよう、オプションを提示するだけです。Draft PRはまだマージできないため、ヒントを省略します。


厳守事項

  • 強制プッシュをしないでください。
  • 自動マージも、自動マージの有効化もしないでください。
  • 明示的な確認なしに、未コミットの変更をコミットしないでください。
  • デフォルトブランチからデフォルトブランチ自身へのPRを作成しないでください。
  • 事前の依頼なしにレビュー担当者、ラベル、担当者を追加しないでください。
  • ブランチ適合性の判断が確定する前にプッシュしないでください。

コメント