本文へ移動
購読
#devtools·FEATURE·2026.09.23 16:49 · 12 min read

Gitブランチ戦略の選び方:小規模チームに最適な運用ルール

Git Flow・GitHub Flow・Trunk-Basedを人数とリリース頻度で比較し、小規模チームにGitHub Flowを勧める理由、ブランチ保護とマージ方式、命名規則、タグ運用、IaCでの適用例まで。

featureブランチを--no-ffでmainにマージし、タグとログのグラフを確認したターミナル
画像:nagoya.dev(実際の画面・実行結果をもとに作成)

Gitブランチ戦略とは、チームが「どのブランチをどこから切り、どこへどうマージし、いつリリースするか」を決めた運用ルールです。Gitの機能ではなくチームの合意事項なので、人数・リリース頻度・並行して保守するバージョン数によって最適解が変わります。

結論を先に書くと、2〜8人程度で1つの本番環境を継続的に更新するチームには、短命ブランチ + Pull Request + main保護のGitHub Flowがもっとも摩擦が少なく、複数バージョンを並行保守する場合だけGit Flowを検討します。以下でその根拠と、設定項目・命名・タグ・インフラコードへの適用まで具体化します。

この記事でわかること

  • Git Flow / GitHub Flow / Trunk-Based Developmentの構造と、人数・リリース頻度による選び方
  • ブランチ保護(PR必須、status check、force push禁止)で実際に有効にする項目
  • Squash / Merge commit / Rebaseの使い分けと、履歴に残るものの違い
  • ブランチ命名とConventional Commitsの形式、annotated tagでのリリースとホットフィックス
  • Terraform・Ansibleなどインフラコードのリポジトリでの運用例(ひとり情シスの場合を含む)

ブランチ戦略が必要な理由

戦略がない状態で起きるのは次の3つです。mainに直接pushされて本番に何が入っているか分からなくなる、長く生きたブランチ同士のマージで大量の競合が出る、障害時にどのコミットへ戻せばよいか判断できない。ブランチ戦略はこの3つに対して「mainは常にデプロイ可能」「変更は小さくレビューを通す」「リリースはタグで特定できる」という不変条件を与えるものです。ルールが多いほど守られなくなるので、この3条件を満たす最小のルールを選びます。

Git Flow / GitHub Flow / Trunk-Based の比較

観点Git FlowGitHub FlowTrunk-Based Development
常設ブランチmain(リリース済み)+ develop(統合用)mainのみmainのみ(trunk)
作業ブランチの寿命feature / release / hotfixで数日〜数週間数時間〜数日数時間〜1日。または直接コミット
リリースreleaseブランチで安定化 → mainへマージしてタグmainへのマージがリリース候補。タグまたは自動デプロイ常にデプロイ可能。機能フラグで公開を制御
ホットフィックスhotfixブランチをmainとdevelopの両方へマージmainから修正ブランチ → PR → マージmainへ直接、または短命ブランチ
必要な前提リリース担当者、複数バージョンの保守CIでのテスト、PRレビュー10分以内で終わる高速なCI、機能フラグ、厚い自動テスト
向くチームパッケージ製品、顧客ごとのバージョン保守Webサービス、社内ツール、インフラコード1日に何度もデプロイする成熟したチーム

Git Flowのdevelopブランチは「mainには未反映だが統合済み」という中間状態を作ります。複数バージョンを出荷する製品では必要な状態ですが、本番が1つしかないWebサービスや社内ツールでは、その中間状態が「developとmainのどちらが正か」という混乱の源になります。Trunk-Basedは理想的ですが、CIが遅い・テストが薄い状態で始めるとmainが頻繁に壊れ、結局ブランチを長生きさせることになります。

小規模チームへの推奨と理由

推奨はGitHub Flowです。常設ブランチがmainだけなので本番と一致するブランチが常に1つに定まること、PRを唯一の入口にすることでレビューとCIを強制できること、ルールが少なくオンボーディングが1日で終わることの3点が理由です。「PRを小さく、1日以内にマージする」を守れば、Trunk-Basedの利点(競合の少なさ、統合の早さ)の大半も得られます。

この推奨が当てはまらないのは、顧客ごとに異なるバージョンを保守する受託・パッケージ開発(Git Flowのrelease / hotfixブランチが必要)と、CIが整備されていないチーム(mainが壊れやすくGitHub Flowの前提が崩れる)です。後者はブランチ戦略より先にCIを用意します。GitHub Actionsで始めるCI/CDのtestジョブがあれば十分です。

判断の問いはいいいえ
複数の本番バージョンを同時に保守する?Git Flow次の問いへ
CIが自動で通り、レビューできる人が自分以外にいる?GitHub FlowGitHub Flow + 自己承認(後述のひとり情シス運用)
1日に複数回デプロイし、機能フラグを運用できる?Trunk-Based(短命ブランチ型)GitHub Flowのまま、PRを小さくする

PRとレビューの運用

GitHub Flowが機能するかどうかはブランチ保護の設定で決まります。リポジトリの Settings → Rules → Rulesets(または従来のBranch protection rules)でmainに次を設定します。

  • Require a pull request before merging:承認1人以上。レビュー相手がいない場合はCI通過のみ必須にする
  • Require status checks to pass:CIのジョブ名(例: test)を指定する。指定しないと「チェックが走らなくても通る」状態になる
  • Require branches to be up to date before merging:古いmainを基にしたPRのマージを防ぐ
  • Block force pushes と Restrict deletions:履歴の書き換えとmain削除を防ぐ
  • 管理者にも適用(bypassを許可しない):例外を作ると「急ぎだから」で崩れる

マージ方式は3つあり、mainの履歴に残るものが違います。

方式mainの履歴向いている場面注意点
Squash and mergePR 1件 = コミット1件小さなPRを高頻度で取り込む。作業中のWIPコミットを隠したいPR内の細かい履歴は消える。マージ後に同じブランチを使い回すと競合する
Merge commit作業ブランチの全コミット + マージコミット作業過程を残したい大きな機能履歴が二股になり、git bisectやgit logが読みにくい
Rebase and merge作業ブランチのコミットを直列に載せ替え直線的な履歴を保ちたいコミットハッシュが変わる。共有ブランチのrebaseは禁止

小規模チームでは「Squash and merge」に統一し、PRタイトルをそのままコミットメッセージにする運用が管理しやすい選択です。PRの粒度は「レビューが15分で終わる」を目安にし、差分が300行を超えるなら分割を検討します。PRテンプレートを置くと、レビューに必要な情報が毎回揃います。

.github/pull_request_template.md
## 目的
(なぜこの変更が必要か。Issueがあれば #番号)

## 変更内容
-

## 確認したこと
- [ ] ローカルでテスト / lint が通る
- [ ] インフラ変更なら terraform plan / ansible --check の結果を貼った
- [ ] ロールバック手順を把握している

ブランチ命名規則とコミットメッセージ

種別ブランチ名の形式例
機能追加feature/<Issue番号>-<要約>feature/42-backup-schedule
不具合修正fix/<Issue番号>-<要約>fix/57-ssh-timeout
緊急修正hotfix/<要約>hotfix/nginx-cert-renew
雑務・依存更新chore/<要約>chore/update-actions

Issue番号を先頭に入れるのは、GitHubの「Development」欄で自動的にIssueと紐づき、ブランチ名だけで文脈が追えるようにするためです。コミットメッセージはConventional Commits(type(scope): 要約)の形式にすると、feat / fix / docs / chore / refactor / ciの種別でリリースノートを自動生成でき、互換性を壊す変更はfeat!:のように!で示せます。日常の流れは次のとおりです。

terminal
git switch main && git pull --ff-only          # ローカルmainを必ずfast-forwardで更新
git switch -c feature/42-backup-schedule
# 作業
git add -A && git commit -m "feat(backup): add nightly PBS job"
git push -u origin feature/42-backup-schedule
gh pr create --fill                             # GitHub CLIでPR作成(タイトル・本文はコミットから)
# マージ後
git switch main && git pull --ff-only && git branch -d feature/42-backup-schedule

git pull --ff-onlyは、ローカルのmainがリモートと分岐していた場合にマージコミットを作らず失敗させる指定です。mainに直接コミットしてしまった事故がここで発覚します。git config --global pull.ff onlyにしておけば毎回のオプション指定は不要です。

Squash mergeを使うチームで、マージ済みのブランチにコミットを足して再度PRを出すと、mainには「1つに潰されたコミット」しかないため同じ変更が二重に見え、競合します。マージしたブランチは削除し、続きは新しいブランチをmainから切ってください。GitHubの「Automatically delete head branches」を有効にすると忘れません。

リリースとタグ、ホットフィックス

リリースの識別はannotated tag(git tag -a)で行います。lightweight tagと違って作成者・日時・メッセージを持ち、git describeの対象になります。バージョンはセマンティックバージョニング(vMAJOR.MINOR.PATCH)で、互換性を壊す変更でMAJOR、機能追加でMINOR、修正でPATCHを上げます。社内ツールやインフラコードのように「バージョン互換」の概念が薄い場合は、v2026.09.23のような日付ベースでも構いません。

terminal
git switch main && git pull --ff-only
git tag -a v1.4.0 -m "Release v1.4.0: nightly backup schedule"
git push origin v1.4.0
gh release create v1.4.0 --generate-notes      # マージ済みPRのタイトルからリリースノートを生成

タグのpushをCIのトリガー(on.push.tags: ['v*'])にすると「タグを打つ = 本番デプロイ」という運用になり、誰がいつ何を出したかがタグに残ります。ホットフィックスはGitHub Flowでは通常の修正と同じで、mainからhotfix/ブランチを切ってPR → マージ → PATCHを上げたタグを打ちます。過去バージョンへの修正が必要なときだけ、そのタグからrelease/1.3ブランチを切り、git cherry-pickでmainの修正コミットを持ち込みます。

タグは「打ち直さない」が原則です。git tag -fで同じ名前を別のコミットに付け替えると、既にそのタグでデプロイした環境やCIのキャッシュと食い違い、障害調査で「v1.4.0」が何を指すのか分からなくなります。間違えたらv1.4.1を打ってください。

情シス内製チーム(インフラコード)での適用例

TerraformやAnsibleのリポジトリでは、mainブランチが「本番の構成」を表します。アプリのコードと違って「レビューで読むべきもの」が差分そのものより実行計画(plan)である点が特徴で、運用は次のとおりです。

  1. 変更は必ずブランチ + PR。PRのCIでterraform planやansible-playbook --check --diffを実行し、結果をPRのコメントに残す
  2. レビュー担当はplanの# forces replacementや- destroyの有無、Ansibleのchanged件数を読む。HCLの体裁はCIのfmt / validateに任せる
  3. mainへのマージでapplyを実行する(GitHub Actionsのenvironment承認付き)。適用結果のログもPRにリンクする
  4. 適用ごとにタグを打つ。障害時は「どのタグから壊れたか」で切り分け、git revertのPRで戻す(git resetで履歴を消さない)
  5. 緊急でコンソールを手で触ったら、事後に必ずコードへ反映するPRを出す。terraform planに差分が出続ける状態を放置しない

ひとり情シスでレビュー相手がいない場合は、「PR必須 + CI通過必須 + 自己承認」にして、PRを変更記録として使うだけでも効果があります。planの結果と適用日時がPRに残るため、ISMSや内部監査で求められる変更管理の証跡になり、後任への引き継ぎ資料にもなります。Ansible側の--check運用はAnsibleでサーバー構築を自動化するで扱っています。

よくある質問

ブランチ戦略は必ず必要?

1人で使い捨ての検証をしている間は不要です。2人以上で同じリポジトリを触る、または本番環境に反映するコードを管理する時点で必要になります。最小構成は「mainを保護し、変更はPR経由」の1ルールだけで、Git Flowのような多段のブランチは複数バージョンの保守が必要になってから足せば間に合います。

mainに直接pushしてはいけない?

本番に繋がるリポジトリでは避けてください。直接pushはCIとレビューを素通りし、「何が本番にあるか」をPRの履歴から追えなくします。ブランチ保護で管理者を含めて禁止し、緊急時もhotfix/ブランチからのPRにします。承認を待つ時間が問題なら、緊急時だけ自己承認を許す運用にすれば直接pushを許す理由はなくなります。

タグはいつ打つ?

本番に出したコミットに、出したタイミングで打ちます。GitHub Flowなら「デプロイしたmainのコミット」に対してannotated tagを付け、タグのpushでデプロイを起動する形にすると打ち忘れがなくなります。インフラコードならapplyごと、アプリならリリースごとで、日付ベースかセマンティックバージョニングかはチームの互換性管理の必要性で決めます。

まとめ

小規模チームの既定解はGitHub Flowで、mainの保護(PR必須、status check、force push禁止、管理者にも適用)とSquash mergeの統一、Issue番号入りのブランチ名、Conventional Commits、annotated tagでのリリース、この5点で「mainは常にデプロイ可能」「変更は小さくレビュー済み」「リリースはタグで特定できる」が揃います。複数バージョンの保守が始まったらGit Flowのrelease / hotfixを足し、CIが10分以内で回るようになったらTrunk-Basedに寄せる、という順で進化させてください。

次に読む

公開 2026.09.23 · 更新 2026.09.24
$ subscribe --weekly
毎週月曜、企業ITとホームラボの要点を5分で。