PR待ち時間を半減するマージ可否の見える化設定


「レビューお願いします」と書いてPRを出したあと、Slackを眺めながら承認を待つ。数時間後にようやく「LGTM」がついたと思ったら、今度は「CIが通ってないからマージできない」と言われる。またしばらく待機。——この時間、積み重なるとけっこうな損失になる。

実はこの「今マージできるのかできないのか分からない」状態、GitHubの設定だけでかなり改善できる。PRを開いた瞬間に「あと何が足りないか」が一目で分かれば、無駄な待機時間はぐっと減る。

「マージ可否」は機械的に判定できる

GitHubの保護ブランチ(Protected branches)やルールセット(Rulesets)を使うと、PRのマージ条件をコードで定義できる。設定した条件を満たさない限り、物理的にマージボタンが押せなくなる。

具体的に指定できる条件はこんな感じ:

  • 必須レビュー数:最低1人(または2人以上)の承認が必要
  • CODEOWNERSの承認:特定ファイルの変更は担当者のレビューが必須
  • 必須ステータスチェック:指定したCIジョブが全て成功している
  • 最新コミットへの承認:古いコミットへの承認は無効化される

これらを設定すると、PR画面の下部に「Merging is blocked」などと表示され、何が足りないかが明確になる。「レビュー待ち」なのか「CI待ち」なのかが一瞬で分かるので、質問したり待ったりする時間が消える。

設定の入り口:Settings → Branches

リポジトリの設定画面から「Branches」を開くと、保護ブランチのルールを追加できる。

mainブランチに対して設定するなら、まずは以下の2つから始めるのが無難:

  1. Require a pull request before mergingをON

    • 直接pushを禁止して、必ずPRを経由させる
    • 「Required approvals」で承認数を指定(最初は1で十分)
  2. Require status checks to pass before mergingをON

    • マージ前に通すべきCIジョブを指定
    • 検索窓にジョブ名を入れて選択する

この2つだけで「承認もCIも通ってないとマージできない」状態が作れる。PR画面を見れば、今何が足りないか全員が同じ情報を見られるようになる。

必須ステータスチェックの落とし穴

便利な必須チェックだが、設定を間違えるとハマる。

ありがちなのが「チェックを送信するGitHub Appを指定し忘れる」パターン。GitHubの仕組み上、チェック結果は誰でも送信できてしまう。悪意はなくても、別のCIサービスが同じ名前のチェックを送ってくることがある。

対策として、ルールセットでは「期待する送信元」を指定できる。GitHub Actionsで動かしているなら、GitHub Actionsを送信元として明示的に指定しておくと安全。

もう一つの落とし穴は「チェックが返ってこない」状態。CIが途中でハングしたとき、いつまでもマージできなくなる。GitHub Enterprise Serverではタイムアウトを分単位で設定できる機能があるが、GitHub.com(Cloud)では使えないケースもあるので、CI側でジョブのタイムアウトを設定しておくのが現実的だ。

レビュー無効化ルール、ONにすべきか

ルールセットには「新しいコミットがpushされたら古い承認を無効化する」オプションがある。

品質を重視するなら確かに正しい。「LGTM」をもらった後にこっそり変更を足してマージ、なんてことを防げる。

ただし、これをONにすると「typo修正の1行pushで再承認待ち」が発生する。修正のたびにレビュアーを呼び戻すことになり、待ち時間は確実に増える。

筆者の意見としては、チーム規模が小さいうちはOFF推奨。信頼関係があるなら、小さな修正のたびに再承認を求める必要はない。チームが大きくなったり、外部コントリビューターが増えてきたらONを検討する、くらいのスタンスでいいと思う。

Merge Queueで「マージ担当」を消す

保護ブランチの設定をしっかりやっても、最後に残るのが「マージボタンを押す人待ち」問題。承認もCIも通ったのに、みんな忙しくて誰もマージしない。

ここで効くのがMerge Queue機能。PRを「Merge when ready」としてキューに入れると、条件が揃った時点でGitHubが自動でマージしてくれる。

流れとしては:

  1. PRを出す
  2. レビュー承認をもらう
  3. 「Merge when ready」でキューに追加
  4. CIが通ったらGitHubが自動マージ

「誰がマージするか」を考えなくていい。自分のPRをキューに入れたら、あとは次のタスクに移れる。

注意点として、Merge Queueは保護ブランチで「Require merge queue」をONにしないと使えない。また、キュー内のPRが衝突したときの挙動など、チームで事前に認識を合わせておく必要がある。

GitHub以外のプラットフォームでも

Bitbucket CloudやGitLabにも似た機能がある。

Bitbucket Cloudでは「Require checks before merge」で必要承認数やビルド成功を要求できる。面白いのが「Merge while build is running」オプション。ビルド以外の条件が揃っていれば、ビルド完了を待たずにマージ予約ができる。CIが長いプロジェクトでは待ち時間短縮に効く。

ただしBitbucketでは、PR作者自身の承認は必要数にカウントされない点に注意。自分で出して自分で承認、はできない仕組みになっている。

GitLabには「Pipelines must succeed」という設定があり、パイプライン成功を必須にできる。注意点として、パイプラインがスキップされた場合もマージできなくなるケースがある。設定次第で逆にハマることもあるので、最初は小さいリポジトリで試すのがいい。

どこから始めるか

いきなり全部の設定をONにすると、既存の開発フローが詰まる可能性がある。

まずは「必須レビュー1人」と「必須ステータスチェック」の2つだけ設定して、1〜2週間様子を見るのがおすすめ。その後、チームの状況を見ながらMerge Queueや承認無効化ルールを足していく。

見える化の効果は地味だが確実。「今何を待っているのか」が明確になるだけで、コミュニケーションコストがかなり減る。設定は10分もあれば終わるので、次のPRを出す前に試してみてほしい。

参考リンク