GitHubのPull Requestは、作るだけなら3分で終わります。ブランチを切ってpushし、画面のボタンを押すだけです。迷うのはその前後で、「Closes #10と書いたのにIssueが閉じない」「テンプレートを置いたのに反映されない」「squashとrebaseのどちらで取り込むべきか」といった運用面の判断が、作り方の解説記事ではほとんど扱われていません。この記事ではブランチ作成からgh pr createまでのコマンド手順に加え、ドラフト・Issue連携・テンプレート・CODEOWNERSの設定、3つのマージ方式の違い、ブランチ保護でレビューを必須化するときの線引きまでをGitHub Docsの記述に沿って整理しました。
まとめ:GitHubのPull Requestを作る手順とマージまでの判断基準
作成の流れは「作業ブランチを切る、コミットしてpushする、baseとcompareを確認して作成する」の3段です。CLIならgh pr create --base main --draftの1行で、画面を開かずにドラフトまで作れます。
つまずきやすいのは設定側です。Issueを自動で閉じるキーワードはデフォルトブランチ宛てのPull Requestでしか効きません。テンプレートもデフォルトブランチにマージされて初めて有効になります。developブランチ宛ての運用では、どちらも黙って無視されます。
マージ方式は、機能単位のPull Requestならsquash、リリースブランチの統合なら通常のマージコミットを選びます。rebase and mergeはコミットのSHAが作り直され、署名検証も外れるため、署名付きコミットを必須にしているリポジトリでは選びません。
レビューの必須化は人数で決めます。2人以上なら承認1件とCI通過を必須に。1人で開発しているリポジトリに「最新pushを本人以外が承認」を入れると、自分のPull Requestを永遠にマージできなくなります。
Pull Requestの仕組みとGit本体のrequest-pullとの違い
Pull RequestはGitのコマンドではなく、GitHubというホスティングサービスの機能です。この区別が分かっていると、ローカルでできることとGitHub上でしかできないことの境目が見えます。
baseとcompareの2ブランチとConversationなど4タブの役割
GitHub DocsのAbout pull requestsは、Pull Requestを「あるブランチから別のブランチへのコード変更のマージ提案」と定義しています。取り込み先がbase、変更を含む側がcompare(head)です。ブランチそのものの考え方はブランチの仕組みと使い方の解説で扱っています。
| タブ・領域 | 表示される内容 | 主に見る人 |
|---|---|---|
| Conversation | 説明文、コメント、レビュー、活動のタイムライン | 作成者・レビュアー |
| Commits | ブランチ上のコミットの時系列 | レビュアー |
| Checks | 自動テストやビルドの結果 | 作成者 |
| Files changed | 差分と行単位のコメント | レビュアー |
| マージボックス | マージ可否と残っている条件 | マージ担当 |
実務で最初に見るのはマージボックスです。承認が足りない、CIが落ちている、コンフリクトがあるといった「なぜマージできないか」が、ここに集約されて表示されます。
Git標準のgit request-pullが出力するプル依頼との違い
Git本体にもgit request-pullというコマンドがあります。git-request-pullの公式ドキュメント(2.56.0で最終更新)は、これを「上流プロジェクトに変更のpullを依頼する文面を生成し、標準出力に出す」ものと説明しています。出てくるのはテキストで、メールに貼って送る使い方を想定したものです。
GitHubのPull Requestは、この依頼文を画面上の対話の場に置き換え、レビュー・CI・マージボタンを一体にした仕組みと捉えると整理できます。だからテンプレートやレビュー必須化といった設定は、Gitではなくリポジトリ側の設定として持つことになります。
ブランチ作成からpush・Pull Request作成までのコマンド手順
ここからは手を動かす部分です。mainを取り込み先とし、featureブランチから作る例で進めます。
git switch -cからgit pushまでのローカル作業4ステップ
最初にmainを最新化してから分岐させます。古いmainから切ると、作成した時点でコンフリクトを抱えたPull Requestになります。
git switch main
git pull origin main
git switch -c feature/login-validation
# 変更を加えたあと
git add -A
git commit -m "ログインフォームの入力チェックを追加"
git push -u origin feature/login-validation
最後の-uで追跡ブランチを設定しておくと、2回目以降はgit pushだけで同じPull Requestにコミットが積まれます。Pull Requestはブランチに紐づくため、作成後に追加でpushしたコミットも自動で反映される仕組みです。
Web画面のCompare & pull requestで作成する際の確認項目
push直後にリポジトリのトップを開くと、「Compare & pull request」ボタンが出ます。Creating a pull requestの手順では、baseのドロップダウンで取り込み先を、compareのドロップダウンで作業ブランチを選び、タイトルと説明を書いてから作成します。
- baseが意図したブランチか(mainかdevelopか)
- compareが今pushしたブランチか
- 差分のファイル数が想定どおりか(無関係なファイルが混ざっていないか)
- 作成ボタンを「Create pull request」と「Create draft pull request」のどちらにするか
1つ目の取り違えが最も多い事故です。base違いのPull Requestは、マージしてから「別ブランチに入っていた」と気づくことになります。作成後でも画面上部のEditからbaseを変更できるので、気づいた時点で直してください。
gh pr createで–base・–draft・–reviewerを指定する例
ブラウザを開かずに作るならGitHub CLIです。gh pr createのマニュアルには、--base(取り込み先)、--head(既定は現在のブランチ)、--draft、--fill(コミット情報からタイトルと本文を埋める)、--reviewerなどのフラグが並んでいます。
gh pr create --base main --title "ログインフォームの入力チェックを追加" \
--body "Closes #42" --draft --reviewer octocat --assignee @me --label enhancement
# コミットメッセージからタイトルと本文を埋める
gh pr create --base main --fill
# 迷ったらブラウザの作成画面を開く
gh pr create --web
--assignee @meで自分を担当者にできます。CLI自体の導入や認証はghコマンドのインストールと使い方にまとめました。
ドラフトとIssue連携・テンプレートでレビュー時の説明不足を防ぐ設定
Pull Requestの質は、作成時に何が書かれているかでほぼ決まります。レビュアーが「これは何のための変更か」を聞き返す往復を、設定で減らせます。
Draftで作成しReady for reviewへ切り替える使い分け
About pull requestsには「ドラフトのPull Requestはマージできず、コードオーナーにも自動でレビュー依頼されない」とあります。作業途中を共有しつつ、正式なレビュー依頼は出したくないときの状態です。
切り替えはChanging the stage of a pull requestのとおり、マージボックスの「Ready for review」を押すだけです。逆にレビュー中のものを戻すときは、右サイドバーのReviewers欄の下にある「Convert to draft」を使います。CLIならgh pr readyです。方針の相談を早めにしたい変更ほど、ドラフトで先に出しておくと手戻りが小さく済みます。
Closes #10など9つのキーワードとデフォルトブランチ限定の条件
説明文にCloses #10と書くと、マージ時にIssue #10が自動で閉じます。Linking a pull request to an issueが挙げるキーワードは、close・closes・closed・fix・fixes・fixed・resolve・resolves・resolvedの9語です。
Closes #10
Fixes octo-org/octo-repo#100
Resolves #10, resolves #123
落とし穴は条件です。同じドキュメントは、キーワードが機能するのはPull Requestがデフォルトブランチを対象にしている場合だけで、それ以外のブランチ宛てではキーワードが無視されると明記しています。git-flowのようにdevelopへ集約する運用では、マージしてもIssueは開いたままです。この場合はリリース時にmainへ入るPull Requestへキーワードを書くか、Issueを手で閉じる運用に決めておきます。
pull_request_template.mdの置き場所3か所と複数テンプレート
Creating a pull request templateによると、テンプレートはリポジトリのルート、docs、.githubのいずれかにpull_request_template.mdとして置きます。
<!-- .github/pull_request_template.md -->
## 変更の目的
Closes #
## 変更内容
-
## 動作確認
- [ ] ローカルでテストが通る
- [ ] 画面で確認した(スクリーンショットを添付)
## レビューで特に見てほしい箇所
複数のテンプレートを使い分けたい場合は.github/PULL_REQUEST_TEMPLATE/ディレクトリに並べ、作成URLのtemplateクエリパラメータで選びます。注意点は1つで、テンプレートはデフォルトブランチにマージされて初めて有効です。作業ブランチに置いただけでは反映されません。
レビュー依頼と手元での動作確認を進めるPull Requestの扱い方
作成したあとは、誰がレビューするかと、レビュアーがどう動作確認するかの2点を詰めます。レビューで何を見るかという観点そのものはコードレビューの目的・観点と運用設計に譲ります。
CODEOWNERSでレビュアーを自動指定する書き方と3MBの上限
毎回レビュアーを手で選ぶ代わりに、CODEOWNERSファイルでパスごとの担当者を決めておけます。About code ownersによれば、置き場所は.github/・ルート・docs/で、複数あればこの順に探して最初に見つかったものを使います。
# .github/CODEOWNERS
* @org/dev-leads
*.sql @org/db-team
/infra/ @org/infra-team
/docs/api/ @tanaka
後に書いた行ほど優先されるため、全体の既定を先頭に置き、個別の指定を下に足していきます。ファイルは3MB未満という上限があり、超えると読み込まれません。ドラフトのPull Requestには自動依頼が飛ばない点も、さきほどのドラフトの仕様と対になっています。
git fetch origin pull/ID/headでPRをローカル検証する手順
差分を読むだけでは分からない挙動は、手元で動かして確かめます。Checking out pull requests locallyには、Pull Requestの番号から参照を取得してブランチを作る方法が載っています。
# Pull Request #57 を pr-57 というブランチとして取得
git fetch origin pull/57/head:pr-57
git switch pr-57
# GitHub CLIなら1行
gh pr checkout 57
この方法はフォークから来たPull Requestにも使えます。相手のリポジトリをremoteに足さなくても、元リポジトリのpull/番号/headという参照に変更が載っているためです。取得したブランチでコンフリクトが出た場合の解き方はGitのコンフリクトの仕組みと解消手順を参照してください。
マージ方式3種の履歴の違いとチーム運用で選ぶ方式・選ばない方式
マージボタンの横の矢印から、3つの方式を選べます。どれでも取り込めますが、あとで履歴を追う、取り消すといった場面で差が出ます。
マージコミット・squash・rebaseで変わる履歴とSHAの扱い
About merge methods on GitHubの記述を表にまとめます。
| 方式 | 取り込み方 | 元のSHA | 向いている場面 |
|---|---|---|---|
| Create a merge commit | 全コミットを--no-ffのマージコミットで統合 |
残る | リリースブランチの統合 |
| Squash and merge | Pull Requestのコミットを1つにまとめる | 残らない(1コミットに集約) | 機能単位のPull Request |
| Rebase and merge | マージコミットを作らず1つずつ積む | 作り直される | コミットを分けて残したい小規模チーム |
機能単位のPull Requestにはsquashを選びます。1機能が1コミットになるので、不具合が出たときにgit revert <SHA>の1行で戻せます。マージ後の取り消し手順はgit mergeの取り消しとrevert -mの使い分けで詳しく扱いました。
署名検証が必要なリポジトリでrebase and mergeを見送る理由
rebase and mergeには、見落とされがちな仕様が2つあります。同じドキュメントは、この方式が「コミッター情報を常に更新し、新しいコミットSHAを作る」こと、そしてheadブランチのコミットが署名検証なしでbaseに追加されることを明記しています。
結論は明確です。署名付きコミットを必須にしているリポジトリでは、rebase and mergeを選ばない。手元で署名したコミットとmainに載るコミットが別物になるため、監査で「誰が書いたコードか」をSHAで追えなくなります。Pull Requestの画面で議論していたSHAとmainのSHAが一致しない点も、障害調査のときに地味に効いてきます。リポジトリ設定で使わない方式のチェックを外し、選択肢から消しておくのが確実です。
ブランチ保護で承認数とCI通過を必須化するときの人数別の線引き
最後に、Pull Requestを経由しないとmainへ入れられないようにする設定です。受託開発で引き渡したリポジトリでも、ここが未設定のまま運用されている例を多く見かけます。
承認1件・古い承認の破棄・最新pushの別人承認を入れる順番
About protected branchesのレビュー関連の設定は、承認数の指定、新しいコミットがpushされたときに古い承認を自動で取り消す設定、最新のpushを本人以外が承認することを求める設定の3つです。
| 開発者の人数 | 承認数 | 古い承認の破棄 | 最新pushの別人承認 |
|---|---|---|---|
| 1人 | 設定しない | 不要 | 入れない |
| 2〜4人 | 1件 | 入れる | 入れる |
| 5人以上・外部委託を含む | 1〜2件+CODEOWNERS | 入れる | 入れる |
1人のリポジトリに承認必須を入れると、自分のPull Requestを自分では承認できないため、マージが止まります。逆に2人以上いるのに古い承認の破棄を入れないと、承認をもらったあとに無関係な変更を足してもそのまま通ってしまう状態です。外部委託先がコミットする構成ではCODEOWNERSと組み合わせ、「Require review from Code Owners」で担当領域ごとに発注側の承認を挟むと、受け入れ検査の記録がPull Requestに残ります。
Require status checksのstrictを有効にしない方がよい場面
CI通過を必須にする設定で選べるモードは2つです。strictはbaseブランチの最新を取り込んだ状態でのチェック成功を求め、looseは最新でなくても通します。CIのトリガー設計はGitHub Actionsのトリガー(on)の設計にまとめています。
strictは安全側ですが、1日に10本以上のPull Requestがマージされるリポジトリでは逆効果です。1本マージされるたびに残り全部が「最新ではない」状態になり、更新とCIの再実行の待ち行列ができます。この規模ではlooseにして、mainへのpush後にもCIを走らせる構成で十分です。マージ頻度が1日数本までならstrictで困ることはありません。
こうした設定は最初に決めても、メンバーの入れ替わりで形骸化しやすい部分です。承認者が退職して誰もマージできない、CODEOWNERSのチーム名が実在しないといった状態から、運用ルールごと引き取ってほしいという相談は保守運用・内製化支援で承っています。
よくある質問
GitHubのPull Requestについて、検索でよく見かける質問に答えます。
Pull Requestとプルリクエスト、PRは同じものですか?
同じものです。GitHubの機能名がPull Requestで、日本語ではプルリクエスト、略してプルリクやPRと呼ばれます。GitLabでは同じ役割の機能をMerge Requestと呼びます。なおGit本体のgit request-pullは、依頼文をテキストで出力するだけのコマンドで、レビューやマージボタンを持つGitHubのPull Requestとは別物です。
Pull Requestを作ったあとに追加でコミットするとどうなりますか?
同じブランチへpushすれば、そのPull Requestに自動で反映されます。作り直す必要はありません。ただし、ブランチ保護で「新しいpushで古い承認を取り消す」設定が入っていると、それまでの承認は無効になり、もう一度承認をもらう必要があります。レビュー指摘への対応コミットを積む運用では、この挙動を前提にレビュアーへ再依頼してください。
Closes #番号を書いたのにIssueが閉じないのはなぜですか?
Pull Requestの宛先がデフォルトブランチでない可能性が高いです。GitHub Docsは、Issueを閉じるキーワードがデフォルトブランチ宛てのPull Requestでのみ機能し、ほかのブランチ宛てでは無視されると明記しています。developへ集約する運用では、mainへ入るリリース用のPull Requestにキーワードを書くか、手動で閉じる運用にします。綴りが9語のいずれかかどうかも確認してください。
マージ後のブランチは削除してもよいですか?
削除して問題ありません。マージ方式がどれであっても、変更はbaseブランチに取り込まれています。マージ後の画面に出る「Delete branch」で消すのが一般的で、リポジトリ設定でマージ時の自動削除も選択可能です。ローカル側はgit switch mainで移動してからgit branch -dで消します。squashで取り込んだ場合はGitが未マージと判定するため、-Dが必要になることがあります。
レビュアーが1人もいない個人開発でもPull Requestを使う意味はありますか?
あります。CIの結果をマージ前に確認できること、変更の目的と経緯がPull Request単位で残ることの2点です。半年後に「なぜこの変更をしたか」を追うとき、コミットメッセージよりPull Requestの説明文のほうが情報量が多くなります。AIによるレビューを組み合わせる方法もあり、CodeRabbitの導入手順と設定で扱っています。ただし承認必須の設定は入れないでください。
関連記事
- Git運用のベストプラクティス|ブランチ戦略・コミット規約・レビュー基準の決め方:Pull Requestの前提になるブランチ戦略とレビュー基準の決め方を扱っています。
- コードレビューとは?目的・観点・進め方と実装現場の運用設計を解説:Pull Requestで何をどう見るかというレビュー観点の解説です。
- ghコマンド(GitHub CLI)とは?インストール方法と使い方・コマンド一覧【v2.101対応】:gh pr create以外のghコマンド全般をまとめています。
- git mergeの取り消し|abort・reset・revert -mの使い分け:マージしたPull Requestを戻すときの手順です。
- コンフリクトとは?Gitで変更が衝突する仕組みと解消手順・予防設計を実装視点で解説:Pull Requestでコンフリクトが出たときの解消手順です。