#5 GitHub Rulesetsでブランチを守る - Python OSS開発記録
Git Flowでブランチ戦略を決めた、次は?「人の注意に頼らず、技術的に間違いを防止」します。
今回はGitHub Rulesetsを使って、mainに直pushを防ぐ設定を、wagtail-reusable-blocksの実例から振り返ります。
KEY TAKEAWAYS
この記事でわかること
- Branch Protection RulesとRulesetsの決定的な違い
- main/develop保護の具体的な設定項目
- 「うっかりミス」を技術的に防止する仕組み作り
用語の定義
TERM 01
Branch Protection Rules
旧方式のブランチ保護機能。ブランチ単位で設定。2024年以降、GitHub Rulesetsへの移行が推奨されている。
TERM 02
GitHub Rulesets
新方式のブランチ・タグ保護機能。パターンマッチで複数ブランチに一括適用可能。Organization単位でも設定可。
TERM 03
Pull Request(PR)
ブランチのマージ前にコードレビューを行う仕組み。変更内容を可視化し、承認フローを経てからマージする。
TERM 04
Force Push
Gitの履歴を強制的に書き換えるpush(git push -f)。共有ブランチで実行すると他の人の作業が消える危険な操作。
なぜ「人の注意」に頼ってはいけないのか
前回、Git Flowでブランチ戦略を決めました。でも「mainに直pushしないでね」と言うだけでは、必ず事故が起きます。
これ、企業プロジェクトでよく見る問題です。
事故例1
「小さい修正だから...」→ うっかりmainにpush → 本番破壊
事故例2
「急いでるから...」→ force push → 他人の作業消失
事故例3
「新人だから知らなかった」→ 直push → 大惨事
解決策: GitHub Rulesetsで技術的に防止すれば、うっかりミスも、知らないミスも、全部ブロックできます。
wagtail-reusable-blocksでは初日にRulesets設定。結果、「mainに直pushしちゃった...」の事故ゼロ。
Branch Protection Rules vs GitHub Rulesets
まず、どっちを使うべきかを決めます。結論から言うと、Rulesetsを使ってください。
決定的な違い
| 項目 | Branch Protection Rules | GitHub Rulesets |
|---|---|---|
| リリース | 2016年〜(旧方式) | 2023年〜(新方式) |
| 設定単位 | ブランチ1つずつ | パターンマッチで一括 |
| スコープ | リポジトリのみ | Organization全体も可 |
| タグ保護 | 不可 | 可能 |
| UI | Settings > Branches | Settings > Rules |
| 今後の対応 | メンテナンスのみ | 新機能追加あり |
なぜRulesetsを使うべきか
wagtail-reusable-blocksでは、最初からRulesetsを採用しました。
理由1
パターンマッチ → main/develop両方を1つのRulesetで保護
理由2
タグ保護も可能 → v0.1.0タグの削除を防げる
理由3
今後の新機能 → Branch Protection Rulesは新機能なし
移行について
既にBranch Protection Rulesを使ってるプロジェクトは、徐々にRulesetsに移行することをGitHubが推奨しています。両方併用も可能ですが、Rulesetsの方が優先されます。
Ruleset設定: main/develop保護
wagtail-reusable-blocksで実際に設定した「default」Rulesetを見ていきます。
「default」Rulesetの全容
基本設定
| 項目 | 設定値 | 意味 |
|---|---|---|
| Name | default | Ruleset名 |
| Enforcement | Active | 有効化(Disabledで無効化可) |
| Target | Branch | ブランチ保護(Tagも選択可) |
| Target branches | main, develop | 保護対象のブランチ |
保護ルール一覧
wagtail-reusable-blocksでは、5つのルールを設定しました。
| ルール | 設定 | 防ぐこと |
|---|---|---|
| Restrict deletions | ✅ 有効 |
main/developの削除を禁止 「間違えて消しちゃった」を防ぐ |
| Block force pushes | ✅ 有効 |
force push(git push -f)を禁止履歴の書き換えを防ぐ |
| Require signed commits | ✅ 有効 |
GPG署名付きコミットのみ許可 なりすましを防ぐ |
| Require a pull request | ✅ 有効(詳細あり) |
直pushを禁止、PR必須 レビューなしのマージを防ぐ |
「Require a pull request」の詳細設定
一番重要なルール。PRを経由しないとマージできない設定です。
| 項目 | 設定値 | 意味 |
|---|---|---|
| Required approving review count | 1 | 承認者1人必要 |
| Dismiss stale reviews on push | ✅ | 新しいpush後、承認を無効化 |
| Require code owner review | ✅ | CODEOWNERS承認必須(トピック#7) |
| Require last push approval | ✅ | 最終pushの後に承認必要 |
| Required review thread resolution | ✅ | すべてのコメント解決必須 |
| Allowed merge methods | Squash only | Squash mergeのみ許可 |
これで防げること
git push origin main→ ブロック(PR必須)git push -f origin main→ ブロック(force push禁止)- PRを自分で承認してマージ → ブロック(別の人の承認必要)
- コメント未解決でマージ → ブロック(全コメント解決必須)
実装: Rulesetの作成手順
実際にGitHub UIで設定していきます。
ステップバイステップ
Step 1: Rulesetsページを開く
- リポジトリ → Settings
- 左サイドバー → Rules → Rulesets
- 「New ruleset」→「New branch ruleset」
Step 2: 基本情報を入力
入力項目:
- Ruleset Name:
default - Enforcement status: Active
- Bypass list: 空(誰もバイパスできない)
Bypass listについて:
管理者でもルールをバイパスできなくします。緊急時は一時的にRulesetを無効化する方が安全。
Step 3: ターゲットブランチを指定
Target branches:
- 「Include default branch」✅
- 「Add target」→ 「Include by pattern」
- Pattern:
develop
# 単一ブランチ main develop # ワイルドカード feature/* release/* # 複数パターン(ORで結合) main, develop, release/*
Step 4: ルールを選択
チェックする項目:
- ✅ Restrict deletions
- ✅ Block force pushes
- ✅ Require signed commits
- ✅ Require a pull request before merging
- Required approvals: 1
- ✅ Dismiss stale pull request approvals when new commits are pushed
- ✅ Require review from Code Owners
- ✅ Require approval of the most recent reviewable push
- ✅ Require conversation resolution before merging
- Allowed merge methods: Squash
Step 5: 保存
「Create」ボタンを押して完了。
確認方法: mainに直pushしてみる → エラーが出ればOK
# テスト: mainに直push git checkout main echo "test" >> README.md git add README.md git commit -m "test" git push origin main # エラーが出る: # remote: error: GH013: Repository rule violations # remote: error: - Changes must be made through a pull request. # → Rulesets動いてる!
OSS vs 企業プロジェクト: 技術的制限の意味
OSS: メンテナーの負担軽減
OSSプロジェクトでは、様々なレベルのコントリビューターが参加します。
全員が完璧にルールを守れるわけではありません。
「mainに直pushしないでね」と毎回コメントするのはメンテナーの負担。
GitHub Rulesetsで技術的にブロックすれば、指摘する手間がゼロになります。
メリット
- 自動的に防げる: 人間が気づかなくても、システムが止めてくれる
- レビュー負担軽減: 「ブランチ間違ってますよ」と指摘する時間がゼロ
- 初心者に優しい: 間違えたらGitHubが教えてくれるので、安心してPRを送れる
技術的予防:
「ルールを守ってね」ではなく、「ルール違反はできない」ようにする。
これがOSSプロジェクトを持続可能にする秘訣です。
企業: 「萎縮」から「安心して失敗できる環境」へ
前回(Topic #4)で触れた「萎縮による開発効率の激減」問題。
GitHub Rulesetsは、この問題を根本から解決します。
従来の問題: 脅しによる教育
- 「mainに直pushするな!壊れるぞ!」 ← 脅し
- 新人は萎縮: 「何をやっても怒られるのでは?」と必要以上に慎重になる
- 「えい」ってやってみることができない: 失敗を恐れて試せない
- 経験値が溜まらない: 試さないから成長しない
- 開発効率が激減: 想像の何倍も遅くなる(日本の大企業に多い)
GitHub Rulesetsによる解決: システムで防御
システムでちゃんと防御してあげれば、逆にできることは何やってもいい。
- 失敗したらシステムが弾く: mainに直pushしようとしても、GitHubが止めてくれる
- 「えい」ってやってみることができる: 間違えても大丈夫だから、試せる
- 経験値が遥かに溜まりやすい: 失敗を恐れずに試せる = 成長が早い
- 心理的安全性: 「これやっていいのかな?」と不安にならない
安心して失敗できる環境:
これは教育の本質です(私が教育機関で働いていた経験から)。
失敗を恐れずに試せる環境こそが、人を育てます。
システムで防御するのは「面倒」ではなく、チーム全体の生産性への投資です。
具体例: mainへの直push禁止
従来(脅しによる教育):
- 先輩: 「mainに直pushするな!本番が壊れるぞ!」
- 新人: 「怖い...何もできない...」(萎縮)
- 結果: 異常に慎重になり、開発効率が激減
GitHub Rulesets(システムによる防御):
- 新人: 「mainにpushしてみよう」
- GitHub: 「エラー: PRを経由してください」(システムが止める)
- 新人: 「なるほど、PRを作ればいいのか」(学習)
- 結果: 失敗を恐れずに試せる。経験値が溜まる。
プロジェクト管理の責任
効果的なプロジェクト管理には、システムやツールに対する理解が重要です。
技術的な背景を持つマネージャーは、以下のような利点があります:
システムを活用した予防: ツールや自動化で問題を未然に防げる
効果的な意思決定: 技術的な制約や可能性を理解した上で判断できる
円滑なコミュニケーション: チームメンバーとの技術的な対話がスムーズになる
重要:
技術的制限を「面倒」と感じるかもしれません。
しかし、新規参画者の目線に立てば、これは最大の親切です。
不十分な説明で脅されて萎縮するより、システムで守られて安心して試せる方が、遥かに生産的です。
よくある質問と回答
FAQ
Q1: ソロ開発でも必要?
A: 必要です。自分のうっかりミスを防げます。「小さい修正だから...」で直pushして後悔、よくあります。
Q2: 承認者1人って、自分で承認できない?
A: できません。「Require approval of the most recent reviewable push」が有効なので、別の人の承認が必須。
Q3: 緊急時はどうする?
A: Rulesetを一時的に「Disabled」に変更。修正後、すぐ「Active」に戻す。Bypass listより安全です。
Q4: 既存のBranch Protection Rulesは?
A: Rulesetsと併用可能ですが、Rulesetsが優先されます。徐々に移行推奨。


まだコメントはありません。最初のコメントを残しませんか?