> ## Documentation Index
> Fetch the complete documentation index at: https://lib.findy.co.jp/llms.txt
> Use this file to discover all available pages before exploring further.

# プルリクエストの書き方 — テンプレート・粒度・スタック

> プルリクエストの基本と運用。テンプレートの設定手順、コミットメッセージとタイトルの規約、粒度の判断基準、依存する変更を積むスタックを説明します。

## 概要

プルリクエストとは、リポジトリへの変更を提案し、その変更についてレビューなどの共同作業を行うための仕組みです。変更はブランチを介して提案されます。適用する内容を含むheadブランチから、変更の適用先であるbaseブランチに向けてプルリクエストを作成し、承認された内容だけが取り込まれます。

## コミットメッセージ

コミットメッセージは、コミットに含まれる変更内容を要約する説明です。書き方をチームの規約として統一すると、履歴のどのコミットが何を変更したのかを一定の形式で追跡できます。

規約には[Conventional Commits](https://www.conventionalcommits.org/ja/v1.0.0/)の形式が広く使われます。`<型>: <要約>`の形式で、先頭に変更の種類を示すプレフィックスを付けます。

| 型 | 用途 | メッセージの例 |
| - | - | - |
| `feat` | 機能の追加 | `feat: プロフィール画面に通知設定を追加` |
| `fix` | バグの修正 | `fix: 日付フィルタの境界値のずれを修正` |
| `docs` | ドキュメントのみの変更 | `docs: セットアップ手順を追記` |
| `refactor` | 挙動を変えないコードの整理 | `refactor: 日付整形処理を共通関数に抽出` |
| `test` | テストの追加・修正 | `test: 境界値のテストケースを追加` |
| `chore` | ビルド設定・依存関係の更新などの雑務 | `chore: 依存パッケージを更新` |

Conventional Commitsと合わせて、[Semantic Versioning](https://semver.org/lang/ja/)を使うことがあります。`MAJOR.MINOR.PATCH`の形式で、変更の互換性に応じて上げるバージョンレベルを決めます。ライブラリやAPIなど、互換性を管理する必要がある開発で利用することがあります。この2つを組み合わせると、コミットメッセージから変更内容を理解しやすくなり、リリースのバージョン番号を機械的に決定できるようになります。

| バージョンレベル | 用途 | バージョンの例 |
| - | - | - |
| `MAJOR` | 後方互換性のない変更 | `1.4.2` → `2.0.0` |
| `MINOR` | 後方互換性のある機能の追加 | `1.4.2` → `1.5.0` |
| `PATCH` | 後方互換性のあるバグ修正 | `1.4.2` → `1.4.3` |

組み合わせる場合は、`<レベル>-<型>: <要約>`のように型の前にバージョンレベルを付けます。破壊的変更を伴う機能追加は`major-feat`、互換性に影響しない小さな機能追加は`patch-feat`のように、型だけでは決まらないバージョンレベルを明示できます。

コミットメッセージは`<型>: <要約>`の1行だけでも成立します。変更の背景や理由を説明したい場合は、空行を挟んで本文やフッターを加えます。

<CodeGroup>
  ```text 要約のみ theme={null}
  fix: 日付フィルタの境界値のずれを修正
  ```

  ```text 本文付き theme={null}
  refactor: 日付整形処理を共通関数に抽出

  画面ごとに重複していた整形ロジックが3箇所で食い違っていたため、
  共通関数に集約して仕様を一本化する。
  ```

  ```text Semantic Versioning付き theme={null}
  major-feat: 通知一覧APIのレスポンスをページネーション形式に変更

  1回のレスポンスで全件を返す形式では通知の増加に耐えられないため、
  ページネーション付きの形式に変更する。

  BREAKING CHANGE: レスポンスのトップレベルが配列からオブジェクトに変わるため、
  クライアントはitems配列から通知を取得するよう修正が必要。
  ```
</CodeGroup>

## タイトル

プルリクエストのタイトルは、変更内容を1行で要約する説明です。タイトルは一覧・通知・マージ後の履歴に表示されるため、本文を開かなくても変更内容を判別できる書き方に統一します。

タイトルはコミットメッセージをベースに、同じくConventional CommitsとSemantic Versioningの形式で決めます。コミットが1つのプルリクエストではそのコミットメッセージをそのまま使い、複数のコミットを含むプルリクエストでは変更全体を代表する型と要約を選びます。

## テンプレート

プルリクエストの作成時に説明欄に自動挿入されるMarkdownのテンプレートを用意することができます。テンプレートがあると、概要・変更点・動作確認といった説明の構成がプルリクエストごとにばらつかず、レビュアーに渡すべき情報を事前にルール化できます。

<Steps>
  <Step title="テンプレートファイルを作成する">
    リポジトリに`.github/PULL_REQUEST_TEMPLATE.md`を作成します。
  </Step>

  <Step title="雛形を書く">
    レビュアーが必要とする情報を、見出しとコメントで区切って並べます。

    ````markdown theme={null}
    ## 概要
    <!-- このプルリクエストで何を行うかを簡潔に記述 -->

    ## 背景/目的
    <!-- この変更が必要になった背景や達成したい目的 -->

    ## 変更内容
    <!-- 変更点を論理単位ごとに箇条書き -->
    -

    <!-- 生成AIにコードを書いてもらった場合、利用したプロンプトを記載する -->
    <details><summary>使用したプロンプト</summary>

    ### 使用したLLMモデル
    <!-- 例: GPT-5.1-Codex, Claude Sonnet 4.5, Gemini 3.0 Pro -->

    ### プロンプト
    ```markdown

    ```
    </details>

    ## テスト計画
    <!-- 実施したテストにチェック -->
    - [ ] ユニットテストを追加・更新した
    - [ ] 既存のテストとCIがすべて通ることを確認した

    ## 動作確認方法
    <!-- レビュアーが動作を確認するための手順と、確認済みの項目 -->
    - [ ] ローカル環境で対象の機能を操作し、期待どおり動作することを確認した
    - [ ] 影響範囲の周辺機能が壊れていないことを確認した

    ## 対応issue
    <!-- このプルリクで対応したイシュー（タイトルと番号） -->

    ## 備考
    ````
  </Step>

  <Step title="デフォルトブランチへマージする">
    テンプレートはデフォルトブランチに存在して初めて適用されます。マージ後に作成されるプルリクエストから、説明欄に雛形が自動で挿入されます。
  </Step>
</Steps>

<Tip>
  テンプレートの内容は定期的に見直しましょう。誰も埋めていないセクションは削ります。レビューで質問することが多い項目などがあれば、セクションとして追加します。
</Tip>

## Draft

Draftとは、レビューの準備が整っていないことを明示するプルリクエストの下書き状態です。Draft状態の間はマージがブロックされるため、作業途中の変更が誤って取り込まれることはありません。

未完成の段階でDraftとしてプルリクエストを開いておくと、実装や設計の方向性について、実コードの差分を見ながら早い段階でフィードバックを得られます。文書や口頭のすり合わせと違い、動くコードを前提に議論できるため、レビュアーと認識を早い段階で合わせられます。

必要なフィードバックが揃い、認識が合ったら、そのまま作業を継続しても、Draftのプルリクエストをcloseして新たにプルリクエストを作り直しても構いません。作業が進むほど方向転換のコストは膨らむため、早い段階で手戻りしてサンクコストを最小限に抑える手段としてDraftは有効です。

作成時に「Create draft pull request」を選択し、レビューを依頼できる状態になったら「Ready for review」でDraft状態を解除します。

## 粒度

プルリクエストの粒度とは、1つのプルリクエストが1つのことに注力できているかという、変更内容の一意性です。差分の行数やファイル数ではなく、変更内容が一意であるかどうかで測ります。

### サイズと粒度の違い

サイズ（変更行数・ファイル数）と粒度（変更内容の一意性）は別の尺度であり、分割の判断に使うのは粒度です。判断基準は、差分が大きいかどうかではなく、プルリクエストの変更内容が一意である（1つのことに注力できている）かどうかです。

| 変更の例 | サイズ | 適切かどうか | 理由 |
| - | - | - | - |
| 1万箇所で利用している関数名の一括リネーム | 大 | 適切 | 変更内容が一意なので1つのプルリクエストで問題ありません |
| データ取得・加工・描画をまとめて実装 | 小〜中 | 不適切 | 異なる変更内容が混在しているため分割します |
| 20行のバグ修正＋ついでの無関係なリファクタ | 小 | 不適切 | 2つの変更が混在しているため分割します |

### なぜ粒度が重要か

焦点の絞られた差分は、レビューする範囲も絞られます。作業量の合計が同じでも、10の変更を1つのプルリクエストでレビューするより、1の変更を10個のプルリクエストに分けてレビューする方が、作成者・レビュアー双方の負担が小さくなります。

<CardGroup cols={2}>
  <Card title="レビューが速い" icon="gauge-high">
    変更内容が一意な差分はレビュアーの頭に収まるため、レビューが後回しにされず、数分で終わります。
  </Card>

  <Card title="切り戻しが容易" icon="rotate-left">
    変更内容が一意なプルリクエストをrevertすれば、その変更だけを巻き戻し、余計なものを巻き込みません。
  </Card>

  <Card title="conflictが減る" icon="code-merge">
    生存期間が短いブランチは、conflictが発生しにくくなります。
  </Card>

  <Card title="原因特定が速い" icon="magnifying-glass">
    変更内容が一意なプルリクエストは影響範囲も絞られるため、障害時の切り分けが速くなります。
  </Card>
</CardGroup>

複数の変更内容が混在したプルリクエストは負の循環を生みます。レビュアーの認知負荷を上げ、レビューは後回しになり、ブランチは長く生き残り、conflictが積み上がって、次のレビューはさらに重くなります。

プルリクエストの粒度は、AIエージェントに作業させるときのコンテキスト管理の観点でも重要です。複数の要件や異なる内容を同じコンテキストで作業させると、焦点が分散して精度が落ちます。変更内容が一意なプルリクエストの粒度で作業させることで、コンテキストが1つのことに集中でき、実装・レビューともに精度が上がります。

### 粒度を適切にするコツ

#### 先に作業を分解する

コードを書く前に独立して作業できるタスクへ分解し、各タスクが1つのプルリクエストに対応するようにします。詳細は[タスク分解](/ja/development/task-breakdown)を参照してください。

#### 迷ったら小さく分割する

適切な粒度に迷ったら、小さい粒度の方を選択します。レビューのやり取りの中で粒度について議論すれば、認識をレビュアーと揃えられます。

大きく作ったプルリクエストを後から分割するよりも、小さく作って後から粒度を大きくするほうが簡単です。迷ったときは小さく出し、段階的に肉付けしていきます。

#### レビューを最優先にする

粒度を小さくすると、マージしないと次の作業に着手できない場面が増えます。ここでレビューが滞るとボトルネックになり、開発スピード全体が低下します。そのため、レビュー依頼が来たら自分の作業より優先して対応します。

作業を中断するコンテキストスイッチが気になるかもしれませんが、粒度が適切なプルリクエストのレビューは数分、時には1分以内で終わるため、中断のコストはわずかです。粒度を適切に保つことが、レビューを最優先にする習慣がチームに根付く土台となります。そのレビューで実際に何を確認するのかは[コードレビュー](/ja/development/code-review)を参照してください。

#### CIを高速に保つ

粒度を小さくするとプルリクエストの数が増え、それに比例してCIの実行回数も増えます。CIが遅いままだと、マージまでの待ち時間が積み重なって開発効率が逆に落ちます。

実行時間は10分未満が目安で、5分を超えたら遅いと判断して改善します。具体的な高速化の手法はCI/CDの[CIを高速に保つ](/ja/development/ci-cd#ciを高速に保つ)を参照してください。

#### デプロイとリリースを分ける

コードを本番環境へ反映するデプロイと、機能をユーザーへ公開するリリースを別の出来事として扱うと、機能全体の完成を待たずに未完成の作業をマージできるため、プルリクエストを小さく出し続けられます。

詳細は[リリース](/ja/development/release-strategy)を参照してください。

## スタック

スタック（stacked pull requests）とは、依存関係のある一連の変更を、互いに積み重なった小さなプルリクエストの連なりに分割する手法です。スタック内の各プルリクエストは1つの変更内容に注力し、baseにはデフォルトブランチではなく直下のプルリクエストのブランチを指定します。

プルリクエストを小さく保つ方針は、タスク間の依存関係と衝突しがちです。タスクBがタスクAの成果の上に成り立つ場合、Aのプルリクエストがレビュー・マージされるまでBのプルリクエストをデフォルトブランチに向けて開けないため、待つか、AとBを1つの大きなプルリクエストに束ねるかの二択になります。スタックはこれを解消します。AのブランチからBのブランチを切り、BのプルリクエストをAのブランチに向けて開くことで、どちらも小さいまま、どちらも待たずに進められます。

### タスクの進め方

依存するタスクの進め方は、待つ・束ねる・スタックの3つに整理できます。それぞれの違いをブランチのツリーで見ていきます。

#### 待つ

タスクAのプルリクエストがマージされるまで、タスクBに着手できません。プルリクエストの粒度は保てますが、タスクBのブランチはタスクAのマージ後にしか切れず、レビュー待ちの間、後続の作業が止まります。

```mermaid theme={null}
%%{init: {'gitGraph': {'mainBranchName': 'main'}}}%%
gitGraph
  commit id: "リリース済み"
  branch task-a
  commit id: "タスクAの実装"
  checkout main
  merge task-a id: "PR-Aのマージを待つ"
  branch task-b
  commit id: "タスクBの実装"
  checkout main
  merge task-b id: "PR-Bのマージ"
```

#### 束ねる

待たない代わりに、タスクAとタスクBを1つのブランチで実装し、1つのプルリクエストにまとめる方法です。作業は止まりませんが、異なる変更内容が混在した大きな差分になり、レビューの負荷が上がります。

```mermaid theme={null}
%%{init: {'gitGraph': {'mainBranchName': 'main'}}}%%
gitGraph
  commit id: "リリース済み"
  branch task-a-b
  commit id: "タスクAの実装"
  commit id: "タスクBの実装"
  checkout main
  merge task-a-b id: "PR: 大きなマージ"
```

#### スタック

AのブランチからBのブランチを切り、BのプルリクエストのbaseをAのブランチへ向けます。どちらのプルリクエストも小さいまま、Aのレビューを待たずにBを進められます。

```mermaid theme={null}
%%{init: {'gitGraph': {'mainBranchName': 'main'}}}%%
gitGraph
  commit id: "リリース済み"
  branch task-a
  commit id: "タスクAの実装（PR-A）"
  branch task-b
  commit id: "タスクBの実装（PR-B）"
```

### 仕組み

スタックはブランチの連鎖で、スタック内の個々のプルリクエストはレイヤーとも呼ばれます。最下層のブランチはデフォルトブランチから切り、その上の各ブランチは直下のブランチから切ります。各プルリクエストはbaseに直下のブランチを指定するため、差分にはその層の変更だけが表示されます。

```mermaid theme={null}
flowchart LR
  subgraph before["マージ前"]
    direction TB
    b3["PR #3: API"] -->|base| b2["PR #2: サービス層"] -->|base| b1["PR #1: モデル"] -->|base| bm["main"]
  end
  subgraph after["PR #1のマージ後"]
    direction TB
    a3["PR #3: API"] -->|base| a2["PR #2: サービス層"] -->|"base（mainへ付け替え）"| am["main（モデルの変更を含む）"]
  end
  before -->|"PR #1をマージ"| after
```

レビューは層ごとに独立して進みます。2つ目のプルリクエスト（図のPR #2）のレビュアーに見えるのはサービス層の差分だけで、その下のモデルの変更は1つ目のプルリクエスト（図のPR #1）に属します。

マージは最下層から順に行います。最下層のプルリクエストがマージされると、GitHubが残りのブランチを自動的にリベースし、次のプルリクエストのbaseをデフォルトブランチに付け替えて、スタックが1層縮みます。最上位のプルリクエストをマージしてスタック全体を一括でマージすることも、下側の一部だけをマージして残りの作業を続けることもできます。プラットフォーム側の挙動の詳細は[GitHub Docs](https://docs.github.com/ja/pull-requests/get-started/about-stacked-prs)を参照してください。

この仕組みによって、スタックには次のメリットがあります。

<CardGroup cols={2}>
  <Card title="粒度を保てる" icon="layer-group">
    依存する変更どうしを1つの大きな差分に束ねず、それぞれを変更内容が一意なプルリクエストのまま保てます。
  </Card>

  <Card title="レビュー待ちでブロックされない" icon="forward">
    下の層のレビューが進行中でも、そのブランチの上で次の層の作業を続けられます。
  </Card>

  <Card title="レビューが小さいまま" icon="eye">
    各プルリクエストにはその層の差分だけが表示されるため、レビューがレビュアーの頭に収まる大きさに保たれます。
  </Card>

  <Card title="依存関係が明示される" icon="diagram-project">
    base連鎖がどの変更がどの変更の上に成り立つかを記録するため、マージ順がプルリクエスト自体から読み取れます。
  </Card>
</CardGroup>

スタックの運用で注意が必要なのは、連鎖の整合性を保つことです。レビュー指摘で下の層が変わると、その上のすべてのブランチを更新後のブランチへリベースし直す必要があります。スタックという手法自体はGitHubに固有のものではなく、以前から手動でも運用できますが、このリベースとbaseの付け替えを毎回手作業で行うことになります。GitHubのスタック対応は、これをカスケードリベースとして自動化しており、プルリクエスト画面からサーバー側で実行するか、`gh stack`拡張でローカルに実行できます。この自動化に加えて、一連のプルリクエストがスタックとして紐付いていることをGitHub側で把握している点も、GitHubでスタックを運用するメリットです。

スタックは、実際に依存し合う変更のためのものです。独立したタスクにスタックは不要で、デフォルトブランチに向けた別々のプルリクエストとして開きます。

### gh stackの使い方

`gh stack`は、スタックのローカルワークフローを1つの単位として扱うGitHub CLIの拡張です。依存順でのブランチの作成と追跡、リベースの維持、push、base連鎖を設定したプルリクエストの作成、層の間の移動をまとめて担います。

<Note>
  スタックのGitHubサーバー側の対応はpublic previewです。全リポジトリへ段階的にロールアウト中のため、`gh stack submit`がリポジトリで失敗する場合は、ロールアウトが未到達の可能性があります。
</Note>

<Steps>
  <Step title="拡張をインストールする">
    ```bash theme={null}
    gh extension install github/gh-stack
    ```
  </Step>

  <Step title="ブランチの連鎖を作る">
    各層を専用のブランチで実装します。新しいブランチは直前のブランチから切り、コミットします。できあがった既存ブランチを、下から上の順に並べてスタックとして採用します。

    ```bash theme={null}
    gh stack init --base main feature/model feature/service feature/api
    ```

    新しく作業を始める場合は、最初のブランチで`gh stack init`を実行してから、`gh stack add`で新しい層を上に積みながら実装することもできます。
  </Step>

  <Step title="プルリクエストを一括作成する">
    ```bash theme={null}
    gh stack submit --auto
    ```

    すべてのブランチをpushし、baseに直下のブランチを設定したプルリクエストをdraftとして一括作成します。説明を記入したらdraftを解除してレビューを依頼します。
  </Step>

  <Step title="最下層からマージする">
    最下層のプルリクエストから順にマージします。上のプルリクエストはGitHub側で自動的にリベースされます。最上位のプルリクエストをマージすると、スタック全体を一括でマージできます。マージ後にローカルブランチを追従させる（fetch・リベース・push・スタック状態の同期をまとめて行う）には、次を実行します。

    ```bash theme={null}
    gh stack sync
    ```
  </Step>
</Steps>

### AIエージェントによるスタックの自動化

スタックは、AIエージェントのワークフローと相性が良い手法です。作業を依存関係付きのIssueに分解しておけば、エージェントが依存順にIssueを実装してIssueごとにブランチを積み、最後にプルリクエストを一括作成できます。人は、小さな層ごとのレビューとマージに集中します。

自動化されたワークフローは、[タスク分解](/ja/development/task-breakdown)の成果物である親Issueを入力として、次の流れで動きます。

<Steps>
  <Step title="親Issueから依存関係を読み取る">
    親IssueのSub-issuesと、Issue間の依存関係を取得します。タスク分解で作った親子Issueと依存関係の設定が、そのまま自動化の入力になります。
  </Step>

  <Step title="依存グラフをスタックに変換する">
    依存関係のグラフを、先に完了すべきIssueが下になる順に並べ、依存を直接・間接にたどってつながるIssueのまとまりを1つのスタックにまとめます。依存のつながりがないまとまりどうしは、複数のエージェントで並列に進められます。

    たとえば、次の依存関係を持つSub-issuesがあるとします。矢印は依存先のIssue（先に完了すべきIssue）を指します。

    ```mermaid theme={null}
    flowchart RL
      B["Issue B"] -->|依存| A["Issue A"]
      C["Issue C"] -->|依存| A
      D["Issue D"] -->|依存| B
      D -->|依存| C
      F["Issue F"] -->|依存| E["Issue E"]
    ```

    このグラフは、次の2つのスタックに変換されます。

    ```mermaid theme={null}
    flowchart BT
      subgraph s1["スタック1"]
        A2["Issue A"] --> B2["Issue B"] --> C2["Issue C"] --> D2["Issue D"]
      end
      subgraph s2["スタック2"]
        E2["Issue E"] --> F2["Issue F"]
      end
    ```

    Issue AからDは、依存をたどるとひとつながりになるため1つのスタックになります。Issue BとCの間に直接の依存はありませんが、AとDを介してつながっているため、同じスタック内で直列に積まれます。Issue EとFのまとまりはAからDと依存のつながりがないため、複数のエージェントで並列に実装できます。
  </Step>

  <Step title="エージェントがブランチを積みながら実装する">
    エージェントはスタック内のIssueを、依存の順序を守って下から実装します。Issueごとにブランチを切ってコミットを積み、Issueとブランチが1対1で対応した連鎖を作ります。先ほどの例のIssue BとCのように互いに依存しないIssueは、同時並列で実装してから連鎖に組み込めます。
  </Step>

  <Step title="プルリクエストを一括作成する">
    連鎖ができあがったら、`gh stack submit --auto`でスタック全体をpushし、base連鎖を設定したプルリクエストを一括作成します。
  </Step>

  <Step title="人がレビューして最下層からマージする">
    人の作業はここからです。層ごとの小さな差分をレビューし、最下層からマージします。下のプルリクエストがマージされると上のプルリクエストはGitHub側で自動的にリベースされるため、マージのたびに手作業でスタックを組み直す必要はありません。スタック内のすべてのプルリクエストがapproveされていれば、最上位のプルリクエストをマージしてスタック全体を一括でマージすることもできます。
  </Step>
</Steps>

この自動化の質は、入力になるタスク分解の質で決まります。要件・完了条件・依存関係を明示したIssueを作ることが、スタックの自動化の前提です。

## 関連ページ

<CardGroup cols={3}>
  <Card title="コードレビュー" icon="eye" href="/ja/development/code-review">
    レビュー依頼が届いたときにレビュアーが何を確認するか。セルフレビューと明確なコメントがやり取りを速く保つ理由。
  </Card>

  <Card title="テストコード" icon="vial" href="/ja/development/testing">
    そもそも変更を検証可能にするもの。テストがプルリクエストをレビューしやすく保つ仕組み。
  </Card>

  <Card title="オンボーディング" icon="door-open" href="/ja/organization/onboarding">
    小さなプルリクエストが、新しいメンバーが毎日のフィードバックから学ぶ最短の道になる理由。
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.