GitHubのbranch protectionをrulesetへ一括移行する: Import branch protection rulesの挙動を確かめる

GitHubのbranch protectionをrulesetへ一括移行する: Import branch protection rulesの挙動を確かめる

branch protection ruleをrulesetへまとめて変換するImport branch protection rulesを試し、1ルールが2つに分かれる理由、FreeプランでのEvaluateの扱い、元のルールの残し方、会話の解決の変換結果を確かめました。
2026.10.21

どうも!オペ部の西村祐二です!

GitHubの branch protection rule を repository ruleset へ変換する機能が、2026-10-20に一括変換へ拡張されました。2026-08-11のchangelogで1ルールずつ変換する Convert to ruleset が追加されていました。今回は、リポジトリ内のbranch protection ruleをまとめて取り込む Import branch protection rules が使えるようになっています。

ルールが多いリポジトリでは、1つずつ変換するより一括インポートのほうが早く終わります。一方で、ボタン1つで複数のrulesetが作られるため、rulesetがどう分かれ、元のルールがどうなるのかは事前に把握しておきたいところです。本記事では、検証用のpublicリポジトリで一括インポートを実行し、生成されたrulesetの中身、プランによる制限、元のルールの扱い、会話の解決(conversation resolution)の変換結果を確かめます。

今回の変更点

  • 対象 / 日付: rulesetが利用可能なすべてのリポジトリ(2026-10-20告知)
  • 変更の要点:
    • Settings → Rulesets の Import branch protection rules から、リポジトリのbranch protection ruleをまとめてrulesetへ変換できる
    • 確認ダイアログ(Review import)で、生成されるrulesetのプレビュー、既存rulesetでカバー済みのルール、1ルールが複数rulesetに分かれるケースを確認できる
    • 適用状態(Active / Evaluate / Disabled)と、作成対象のrulesetを選べる
    • 作成後に、元のbranch protection ruleを残すか削除するかを選べる
  • 公式リンク: Bulk migrate branch protections to rulesets for a repository

2026-10-21時点では、GitHub Docsの変換ページは1ルールずつの Convert to ruleset の説明のままで、一括インポートの手順はchangelogにだけ書かれています。

なぜrulesetへ移行するのか

GitHub Docsとchangelogでは、rulesetの利点として次の点が挙げられています。

  • 複数ブランチへのパターン適用: 1つのrulesetを、パターンマッチで複数ブランチへ適用できる
  • ルールの重ね掛け: 同じブランチに複数のrulesetを同時に適用し、レイヤーとしてポリシーを組める
  • Organization / Enterprise単位の管理: リポジトリをまたいで同じrulesetを適用できる
  • 細かいbypass権限: ユーザー、チーム、アプリごとに、だれがルールを迂回できるかを指定できる
  • read権限での可視化: read権限を持つ人がactiveなrulesetを閲覧でき、開発者は自分に適用されるルールを、監査者はadmin権限なしで保護状況を確認できる

一括インポートを試す

検証環境

  • github.com のFreeプランのアカウント
  • 検証用のpublicリポジトリ(検証後に削除)
  • 2026-10-21に実施

Freeプランのprivateリポジトリではrulesetを使えないため、publicリポジトリで試しています。

変換前に、次の3つのbranch protection ruleと、develop を対象にした既存のrulesetを用意しました。

パターン branch protectionの設定
main 承認1件必須、ステータスチェック test 必須(マージ前にブランチを最新にすることも必須)、会話の解決を必須
release/* 直線的な履歴(linear history)を必須
develop 直線的な履歴を必須。直線的な履歴・force push禁止・削除禁止を含む既存ruleset develop-linear-history でカバー済み

いずれも「管理者にも適用する(Do not allow bypassing the above settings)」は無効のままです。会話の解決の扱いを確かめるため、後から hotfix/* のルールも追加して取り込んでいます(後述)。

Review importで生成結果を確認する

branch protection ruleがあるリポジトリでSettings → Rulesetsを開くと、変換を促すバナーと Import branch protection rules ボタンが表示されました。

Rulesets画面に表示されたImport branch protection rulesのバナー

ボタンを押すと、Review importダイアログが開きます。

Review importダイアログ。mainとrelease/*がそれぞれ2つのrulesetに分かれ、developは既存rulesetでカバー済みと表示されている

ダイアログからは次のことが読み取れます。

  • 見出しは 4 rulesets will be created from 2 branch protection rules. で、main と release/* の2つから4つのrulesetが作られる
  • main と release/* は、それぞれ -1 / -2 の2つのrulesetに分かれる。ruleset名は入力欄で変更できる
  • develop はチェックボックスが無効になり、Already covered by an existing ruleset と表示される。既存rulesetでカバー済みのルールは取り込み対象から外れる
  • main には main is not covered / Rulesets do not strictly require status checks / No ruleset contains all required status checks、release/* には No coverage という注記が出る。既存rulesetでのカバー状況や、branch protectionと挙動が完全には一致しない設定が、作成前に示される

1つのルールが2つのrulesetに分かれる理由

後述の手順で作成したrulesetの中身を gh api repos/<owner>/<repo>/rulesets/<id> で確認すると、次のように分かれていました。

ruleset bypass 含まれるルール
main-1 なし 削除の禁止、force pushの禁止
main-2 Repository admin ステータスチェック必須(strict)、pull request(承認1件、会話の解決を必須)
release/*-1 なし 削除の禁止、force pushの禁止
release/*-2 Repository admin 直線的な履歴を必須

bypassの有無で分かれています。About protected branchesでは、branch protectionの制限は既定ではadmin権限を持つ人に適用されないと説明されています。今回のルールも、承認やステータスチェックなどは管理者に適用しない設定でした。

一方、削除とforce pushの禁止はbypassなしのrulesetに入りました。この結果から、変換時には削除とforce pushの禁止を管理者にも適用される制限として扱い、管理者がbypassできる部分とは別のrulesetに分けていると読めます。rulesetではbypassをruleset単位で設定するため、bypassの扱いが違うルールを1つにまとめられません。

changelogには、元の挙動を保つために1つのbranch protection ruleから複数のrulesetが作られる場合がある、と書かれています。今回の分割はこのケースに当たります。ruleset名は取り込み時に変更できるので、main-protect-all と main-admin-bypass のように役割が分かる名前にしておくと、後で一覧を見たときに迷いにくくなります。

Evaluateは画面に表示されるがFreeプランでは作れない

Enforcement statusのドロップダウンには、FreeプランでもActive / Evaluate / Disabledの3つが表示されました。既定はActiveです。なお、Evaluateはルールを強制せずに、違反になる操作をRule Insightsで記録するだけのモードです。

Evaluateを選んで Create rulesets を押すと、次のエラーが表示され、rulesetは作られませんでした。

Evaluateを選んで作成するとプラン非対応のエラーが表示される

Enforcement evaluate option is not supported on this plan. Please upgrade to Enterprise to enable it.

REST APIで enforcement: "evaluate" のrulesetを作ろうとしても、同じ文言の422エラーが返りました。GitHub Docsでも、Evaluateの説明はGitHub Enterprise Cloud / Server向けのページにだけ表示されます。試したのはFreeプランだけですが、エラー文言とDocsの記載から、EvaluateはEnterprise向けの機能だと考えられます。Evaluateが使えない場合は、Activeで作成して元のルールを残し、並行して運用することになります。

元のbranch protection ruleを残すか削除するか

Activeに戻して Create rulesets を押すと、元のルールを削除するかを確認するダイアログが出ました。

rulesetを作成した後、元のbranch protection ruleを残すか削除するかを選ぶダイアログ

Keep rules を選ぶと、4つのrulesetがActiveで追加されました。

一括インポート後のruleset一覧。main-1、main-2、release/*-1、release/*-2が追加されている

Branchesの画面に移ると、元のbranch protection ruleはすべて残ったまま、それぞれに This rule is fully covered by rulesets and can be safely deleted. と Delete ボタンが表示されていました。

Branches画面。3つのbranch protection ruleすべてにrulesetでカバー済みと表示されている

GitHub Docsによると、元のルールを残した場合はbranch protectionとActiveのrulesetが同時に適用され、変更は両方を満たす必要があります。残しておけば、rulesetを作った直後に保護が抜けることはありません。Branches画面の表示でカバー状況を確かめてから、Delete で元のルールを消せます。

後述の hotfix/* を取り込んだときは、削除するほうを選びました。対象が1件のときはボタンが単数形の Delete branch protection rule になり、ruleset作成と同時に元のルールがbranch protection ruleの一覧から消えました。

会話の解決はpull requestルールとして変換される

GitHub Docsには、変換は Require conversation resolution before merging を除くすべてのbranch protection種別をカバーする、と書かれています。除外の理由は、rulesetでは会話の解決がpull requestルールの一部で、pull requestルールが有効なときだけ適用されるため、1対1で対応しないという点です。

ところが、実際に一括インポートで試すと、会話の解決も変換されていました。

  • 承認必須と併用していた main では、main-2 のpull requestルールに required_review_thread_resolution: true として引き継がれた
  • 1回目のインポート後に、会話の解決だけを必須にした hotfix/* を追加して取り込むと、hotfix/*-1(bypassなし、削除とforce pushの禁止)と hotfix/*-2(Repository adminがbypass)の2つに分かれた。hotfix/*-2 には、承認0件のpull requestルール(required_approving_review_count: 0, required_review_thread_resolution: true)が入った

hotfix/* を取り込むときには、Review importに次の注記が表示されました。先に変換した3つのルールは、この時点では Already covered by an existing ruleset になっています。

会話の解決だけを必須にしたルールを取り込むと、rulesetではpull requestも必須になるという注記が表示される

注記によると、rulesetで会話の解決を必須にするとpull requestも必須になり、pull requestを経由しないマージで迂回できなくなります。今回は実際のpushまでは試していませんが、会話の解決だけを必須にしていたブランチでは、bypassに入っている管理者を除き、変換後はpull requestを経由しないと変更を入れられなくなりそうです。直接pushを許していたブランチを移すときは、この差を事前に確認しておく必要があります。

1ルールずつ変換する場合(Convert to ruleset)

2026-08-11に追加された、1ルールずつ変換する方法もそのまま使えます。今回は一括インポートだけを試したため、ここはGitHub Docsの記載に基づく整理です。

  1. リポジトリの Settings → Branches を開く
  2. Branch protection rules の一覧から対象のルールを見つけ、Convert to ruleset を押す
  3. ruleset名を設定し、New behavior セクションで変更点を確認する
  4. 必要なら Delete branch protection rule once migration is done を選び、Create ruleset(複数できる場合は Create 2 rulesets のような表示)を押す

Enterprise以外のDocsでは、この方法で作られるrulesetは常にActiveと説明されています。Docsの手順には、既存rulesetでカバー済みのルールをまとめて確認する工程はありません。特定のルールだけ先に移すならこちら、リポジトリ全体を移すなら一括インポート、と使い分けられます。

まとめ

GitHubのbranch protection ruleは、2026-10-20からSettings → Rulesetsの Import branch protection rules でまとめてrulesetへ変換できるようになりました。Review importで、生成されるrulesetと既存rulesetでカバー済みのルールを確認してから、元のルールを残すか削除するかまでを1つの流れで選べます。

Freeプランのpublicリポジトリで試すと、管理者のbypassの有無で1ルールが2つのrulesetに分かれました。Evaluateはドロップダウンに表示されるものの、Freeプランでは作成できず、エラーはEnterpriseへのアップグレードを求めていました。会話の解決は、Docsでは変換対象外とされていますが、実際にはpull requestルールの一部として引き継がれ、pull requestの経由が必須になります。

移行するときは元のルールをいったん残し、Branches画面でカバー状況を確かめてから削除すると、保護が途切れずに済みます。特定のルールだけ移したい場合は、従来の Convert to ruleset も使えます。

誰かの参考になれば幸いです。


参考リンク:


そのCCoE、つくって終わりになっていませんか

ガバナンスのルールも組織ポリシーも、整えた直後はちゃんと機能する。でも運用が属人化すれば、CCoEはいつのまにか形だけに。ベンダー依存から内製へ踏み出すために、中の人として実行まで伴走する。立ち上げと定着の進め方を、無料資料にまとめました。

CCoE総合支援

CCoE立ち上げ資料をダウンロード

この記事をシェアする

関連記事