
GitHubのbranch protectionをrulesetへ一括移行する: Import branch protection rulesの挙動を確かめる
どうも!オペ部の西村祐二です!
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 ボタンが表示されました。

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

ダイアログからは次のことが読み取れます。
- 見出しは
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は作られませんでした。

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 を押すと、元のルールを削除するかを確認するダイアログが出ました。

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

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

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も必須になり、pull requestを経由しないマージで迂回できなくなります。今回は実際のpushまでは試していませんが、会話の解決だけを必須にしていたブランチでは、bypassに入っている管理者を除き、変換後はpull requestを経由しないと変更を入れられなくなりそうです。直接pushを許していたブランチを移すときは、この差を事前に確認しておく必要があります。
1ルールずつ変換する場合(Convert to ruleset)
2026-08-11に追加された、1ルールずつ変換する方法もそのまま使えます。今回は一括インポートだけを試したため、ここはGitHub Docsの記載に基づく整理です。
- リポジトリの Settings → Branches を開く
- Branch protection rules の一覧から対象のルールを見つけ、Convert to ruleset を押す
- ruleset名を設定し、New behavior セクションで変更点を確認する
- 必要なら 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 も使えます。
誰かの参考になれば幸いです。
参考リンク:
- Bulk migrate branch protections to rulesets for a repository - GitHub Changelog
- Automatically migrate branch protection rules to repository rulesets - GitHub Changelog
- Converting branch protections to rulesets - GitHub Docs
- About rulesets - GitHub Docs
- About protected branches - GitHub Docs
- Create a repository ruleset - GitHub REST API










