# ガードレールを多層で組む — ブランチ保護と git worktree 運用を監査して固めた

> ソロ＋AI エージェント常用のモノレポで、main のブランチ保護（GitHub Ruleset）と git worktree の運用が本当に妥当かをディープリサーチ報告と突き合わせて監査した記録。報告の推奨をそのまま鵜呑みにせず、この環境（Codespaces / pnpm ハードリンク共有）に本当に効くものだけを適用し、規模が育ってから効くものは Roadmap に後回しした。多層防御（ローカル＝利便性 / サーバー側＝強制）の設計と、実際に入れたコードを一次情報で残します。

- 出典: SUZ-LAB（実験ログ / 一次情報）
- URL: https://suz-lab.co.jp/logs/hardening-branch-protection-and-worktrees
- 公開: 2026-07-08
- 更新: 2026-07-08
- 著者: Hiro（主任研究員・https://suz-lab.co.jp/researchers/hiro・X: https://x.com/suz_lab_hiro）
- 柱: テクノロジー
- タグ: #Git #GitHub #ブランチ保護 #worktree #pnpm #AI #多層防御
- カバー画像: https://suz-lab.co.jp/assets/logs/hardening-branch-protection-and-worktrees.png?v=b76bccf8

---


## 何が問題だったか

このリポジトリは **ソロ＋AI エージェント常用**という、少し特殊な体制で回している。人間が
コードを書く量より、Claude Code / Copilot が書く量のほうが多い日もある。だからこそ
「エージェントが `main` に直接コミットする」「レビュー指摘を自分で解決してマージを通す」
といった**習慣的な事故**を、仕組みで止めておく必要がある。

すでに手は打ってあった——`main` はリポジトリ Ruleset で保護し、ローカルには
`.githooks/pre-commit` を置き、worktree はヘルパスクリプト（`wt:new` / `wt:rm`）で規約どおりに
作らせている。ただ、それらが**本当に妥当か**、そして**この環境に固有の落とし穴**を踏んで
いないかは、腰を据えて検証していなかった。

そこで、ブランチ保護と worktree 運用に絞ってディープリサーチをかけ、その報告書を
**監査のチェックリスト**として使い、現状と一つずつ突き合わせた。ポイントは、報告の推奨を
そのまま適用しないこと。一般論として正しくても、**この repo（Codespaces / pnpm の
ハードリンク共有）で本当に効くもの**だけを入れ、いま効かないものは Roadmap に後回しした。

## 設計 — なぜ「多層」で組むのか

出発点にした原則はひとつ。**ローカルのフックは利便性であって、セキュリティ保証ではない。**
`git commit --no-verify` や GUI クライアント経由で簡単に迂回できる。だから防御は 2 層に分け、
役割をはっきり分離する。

- **サーバー側＝強制（迂回不可）**: GitHub Ruleset。`main` への直 push 禁止・force push /
  削除禁止・PR 必須・**未解決レビュースレッドがあるとマージ不可**。ここは API 側で拒否されるので、
  人間だろうと AI だろうと破れない。
- **ローカル＝利便性（手戻り防止）**: `.githooks/pre-commit`。`main` でのコミットを
  **コミットが積まれる前に**弾き、「ブランチを切り直せ」と教える。push して初めて Ruleset に
  跳ね返される、という無駄な往復をなくすためのもの。

この分離は、少人数体制のレビュー設計にも効いている。承認レビュー数は **0**（実質セルフマージに
なる承認要求で速度を殺さない）だが、**未解決スレッド解決は必須**。機械チェックで拾えない
論理・設計の指摘だけをマージゲートにする、という割り切りだ。ただしこれには穴がある——
**AI エージェントが人間の指摘スレッドを自分で Resolve してマージを通せてしまう**。ここは
仕組みでなく規約で塞ぎ、リポジトリの `AGENTS.md` に「人手の監査コメントは人間が解決する」と明記した。

## やってみたこと — 適用したもの

報告のうち、**この環境に実際に効く**と検証できたものだけを入れた。

### 1. `extensions.worktreeConfig` で hooksPath 上書きを予防する

いちばん効いたのはこれ。AI エージェントのツールが git worktree を自動生成するとき、共有の
`.git/config` の `core.hooksPath` を勝手に書き換え、**設定したフックを丸ごと無効化する**不具合が
報告されている。ここでは pre-commit フックがこの経路で死ぬと、`main` 直コミットのガードが
外れる。

対策として、ルートの `prepare` スクリプトに `extensions.worktreeConfig true` を足した。

```json
"prepare": "git rev-parse --git-dir >/dev/null 2>&1 && git config extensions.worktreeConfig true && git config core.hooksPath .githooks || true",
```

`prepare` は `pnpm install` のたびに走る。各 worktree でも `pnpm install` は必ず走るので、
**万一 `core.hooksPath` が上書きされても、次のインストールで `.githooks` に貼り直される**
（自己修復）。worktreeConfig を立てておくのは、worktree ごとに設定を独立管理できるようにする
ための予防線。

### 2. worktree の `pnpm install` を `--prefer-offline` に

共有ストア（`/workspaces/.pnpm-store`）は worktree と同じ `/workspaces` ボリューム上にあるので、
依存はハードリンクで解決される。`wt:new` の `pnpm install` に `--prefer-offline` を足し、
レジストリの再検証を省いて**新規 worktree の準備を数秒で終わらせる**ようにした。

## 後回しにしたもの（Roadmap の TODO に落とした）

報告のうち、いま入れる必要はないが**規模が育つと効いてくる**一手は、無理に前倒しせず
Roadmap の TODO として残した。監査の価値は「入れる」判断だけでなく「今はやらない」判断にもある。

- **Lefthook への移行** … いまのシェル製 `pre-commit` は依存ゼロで軽く、単一のガードには十分。
  だがモノレポでリンター・型チェック・整形を**並列**で走らせたくなったら、Go 製の Lefthook が
  `lefthook.yml` 一本でそれを賄える。フックが増える前に、が目安。
- **Ruleset のさらなる堅牢化** … `required_signatures`（署名必須）と、CI の自動修正コミットを
  GitHub API 経由で **Verified 署名**する仕組み、`.github/workflows/*` など壊れると痛い経路への
  CODEOWNERS。いずれも GitHub 側の設定変更が要るので、コードとは別レイヤーの一手として分けた。

## 検証

コードに触れた分は、壊れていないことを機械的に確かめた。

```bash
pnpm typecheck   # 型チェック … パス
pnpm lint        # ESLint … パス
git config --get extensions.worktreeConfig   # → true
git config --get core.hooksPath              # → .githooks
```

`prepare` の変更は「`pnpm install` を一度回すと `worktreeConfig` と `hooksPath` の両方が
設定される」ことを確認。`wt:new` / `wt:rm` の挙動（作成 → install → 削除 → prune）も一通り通した。

## 学び

- **研究報告は「チェックリスト」であって「手順書」ではない。** 一般論として正しい推奨でも、
  自分の環境で成り立つ前提かを一つずつ検証してから入れる。鵜呑みにしてコピペすると、この repo に
  効かない設定を触って別のリスクを持ち込みかねない。**今すぐ効くものだけを入れ、残りは後回しにする**
  切り分けそのものが監査の成果だ。
- **強制と利便性を分けると設計が澄む。** 破れてはいけないもの（`main` 保護）はサーバー側の
  Ruleset に、手戻りを減らすだけのもの（コミット前の警告）はローカルフックに。役割を混同しない。
- **AI 常用ならではの穴を先に塞ぐ。** hooksPath の上書き、レビュースレッドの自主解決——人間だけの
  チームなら起きにくい事故が、エージェントでは「習慣」として起きうる。仕組みで塞げるものは
  仕組みで、塞げないものは規約で明示する。次は Roadmap に落とした Lefthook 化と Ruleset 堅牢化を、
  必要になったタイミングで一つずつ倒していく。

