はじめに:なぜブランチ戦略が重要なのか

前回の記事でGitの基本概念とGitHubリポジトリの作成について学びました。今回は、実際のチームプロジェクトで最も重要な要素の一つであるブランチ戦略について詳しく見ていきます。

一人で開発していたときは特に問題なかったことが、チームメンバーが増えると複雑になり始めます。「誰がどの機能を開発しているんだっけ?」「このコード、なぜ突然変わったの?」「デプロイ前に急いでバグを直さないといけないんだけど、どうすればいい?」といった状況が頻繁に発生しますよね。まさにこのような問題を解決するためにブランチ戦略が必要なのです。

よく設計されたブランチ戦略は、チームメンバー間のコンフリクトを最小化し、デプロイプロセスを体系化し、コード品質を維持するのに核心的な役割を果たします。これから、ブランチの基本概念から実務で広く使われている戦略まで一つずつ見ていきましょう。

1. ブランチとは何か

1.1 ブランチの概念

ブランチ(Branch)は文字通り「枝」という意味です。木の幹から複数の枝が伸びていくように、一つのコードベースから複数の独立した作業フローを作ることができます。

ブランチを使用すると、メインコードに影響を与えずに新しい機能を開発したり、バグを修正したりできます。作業が完了したら再びメインコードにマージ(merge)する方式でコラボレーションが行われます。

ブランチは特定のコミットを指すポインタです。新しいブランチを作るということは、現在の位置で新しいポインタを生成することであり、その後各ブランチでのコミットは、そのブランチのポインタだけを移動させます。

1.2 ブランチが必要な理由

ブランチなしで作業することを想像してみてください。すべてのチームメンバーが一つのコード上で同時に作業したらどうなるでしょうか?

  • コードコンフリクトの頻発:同じファイルを複数人が修正するとコンフリクトが頻繁に発生します。
  • 不完全なコードのデプロイ:開発中の機能が誤ってデプロイされる可能性があります。
  • ロールバックの困難さ:問題が発生したときに特定の機能だけを元に戻すのが難しくなります。
  • 並列作業の不可:一人が作業を終えるまで他の人が待たなければなりません。

ブランチを使用すると、これらの問題を自然に解決できます。それぞれ独立した空間で作業し、完成したものだけをマージすればいいのですから。

2. ブランチの基本コマンド

2.1 ブランチの作成と確認

最も基本的なブランチ関連コマンドを見ていきましょう。

# 現在のブランチ一覧を確認
git branch

# リモートブランチを含むすべてのブランチを確認
git branch -a

# 新しいブランチを作成(現在のブランチから分岐)
git branch feature/login

# ブランチ作成と同時に移動
git checkout -b feature/login

# または最新の方法で
git switch -c feature/login

2.2 ブランチの移動:checkout vs switch

Git 2.23バージョンからswitchコマンドが導入されました。従来のcheckoutはブランチ移動の他にファイル復元など複数の機能を担当していましたが、これを分離して直感性を高めたものです。

# 従来の方法(引き続き使用可能)
git checkout feature/login

# 新しい方法(推奨)
git switch feature/login

# 前のブランチに戻る
git switch -

個人的にはswitchコマンドをより推奨します。用途が明確で、誤ってファイルを上書きしてしまうことを防げますから。

2.3 ブランチのマージ(Merge)

作業が完了したブランチを別のブランチに統合することをマージ(merge)と言います。

# mainブランチに移動
git switch main

# feature/loginブランチをmainにマージ
git merge feature/login

# マージ完了後、ブランチを削除(オプション)
git branch -d feature/login

2.4 ブランチの削除

# マージ済みのブランチを削除
git branch -d feature/login

# マージされていないブランチを強制削除(注意が必要)
git branch -D feature/experimental

# リモートブランチを削除
git push origin --delete feature/login

3. Git Flow戦略

3.1 Git Flowとは

Git Flowは2010年にVincent Driessenが提案したブランチ戦略で、大規模プロジェクトで広く使用されています。明確なルールと構造を持っているため、チームメンバー全員が一貫した方法で作業できます。

3.2 Git Flowのブランチ種類

メインブランチ(常に維持)

  • main(またはmaster):プロダクションにデプロイされるコードのみ存在します。すべてのコミットにはバージョンタグが付きます。
  • develop:次のリリースに向けた開発が進行するブランチです。featureブランチがここにマージされます。

補助ブランチ(必要時に作成後削除)

  • feature/*:新機能開発用。developから分岐し、developにマージされます。
  • release/*:リリース準備用。developから分岐し、mainとdevelop両方にマージされます。
  • hotfix/*:緊急バグ修正用。mainから分岐し、mainとdevelop両方にマージされます。

3.3 Git Flowの実際の使用例

# 1. 新機能開発を開始
git switch develop
git switch -c feature/user-authentication

# 2. 機能開発完了後、developにマージ
git switch develop
git merge --no-ff feature/user-authentication
git branch -d feature/user-authentication

# 3. リリース準備
git switch -c release/1.0.0 develop

# 4. リリースブランチで最終修正後、mainにマージ
git switch main
git merge --no-ff release/1.0.0
git tag -a v1.0.0 -m "Version 1.0.0"

# 5. developにもマージ
git switch develop
git merge --no-ff release/1.0.0
git branch -d release/1.0.0

# 6. 緊急バグ修正(hotfix)
git switch main
git switch -c hotfix/critical-bug

# 7. 修正後、mainとdevelop両方にマージ
git switch main
git merge --no-ff hotfix/critical-bug
git tag -a v1.0.1 -m "Hotfix: critical bug"
git switch develop
git merge --no-ff hotfix/critical-bug
git branch -d hotfix/critical-bug

3.4 Git Flowのメリット・デメリット

メリット

  • 明確なルールで大規模チームでも一貫性を維持
  • リリースバージョン管理が体系的
  • プロダクションと開発コードが明確に分離
  • 緊急修正に対する明確なプロセスを提供

デメリット

  • ブランチが多くなり複雑になる可能性
  • 頻繁なデプロイ(CI/CD)には適さない
  • 小規模プロジェクトには過剰なオーバーヘッド

4. GitHub Flow戦略

4.1 GitHub Flowとは

GitHub FlowはGit Flowの複雑さを減らした、シンプルで効率的な戦略です。GitHubが提案し、CI/CD環境に最適化されています。

4.2 GitHub Flowのルール

  1. mainブランチは常にデプロイ可能な状態を維持
  2. 新しい作業はmainからブランチを作成して開始
  3. ブランチ名は説明的に記述(例:feature/add-login、fix/header-bug)
  4. 作業中は頻繁にリモートにpushしてバックアップ
  5. 準備ができたらPull Requestを作成
  6. コードレビュー後、mainにマージ
  7. マージ後すぐにデプロイ

4.3 GitHub Flowの実際の使用例

# 1. mainから新しいブランチを作成
git switch main
git pull origin main
git switch -c feature/shopping-cart

# 2. 作業しながら頻繁にコミット
git add .
git commit -m "Add cart item component"
git push origin feature/shopping-cart

# 3. 追加作業
git add .
git commit -m "Implement cart total calculation"
git push origin feature/shopping-cart

# 4. GitHubでPull Requestを作成
# (Webインターフェースまたはgh CLIを使用)

# 5. レビュー完了後、mainにマージ(通常GitHub Webで実行)

# 6. ローカルをクリーンアップ
git switch main
git pull origin main
git branch -d feature/shopping-cart

4.4 GitHub Flowのメリット・デメリット

メリット

  • 非常にシンプルで理解しやすい
  • 継続的デプロイ(CD)に適している
  • 小規模チームに理想的
  • 素早いフィードバックサイクル

デメリット

  • リリースバージョン管理が明示的でない
  • 複数バージョンを同時に維持する必要がある場合は適さない

5. Trunk Based Development

5.1 Trunk Based Developmentとは

Trunk Based Development(TBD)は、すべての開発者が一つのブランチ(trunkまたはmain)で直接作業する方式です。Google、Facebookなどの大手テック企業で使用されています。

5.2 コア原則

  • 短命なブランチ:ブランチは1日以内にマージ
  • 小さな単位のコミット:大きな機能も小さく分けて頻繁にコミット
  • Feature Flagの活用:完成していない機能はフラグで非表示に
  • 強力なテスト自動化:すべてのコミットに対して自動テストを実行

5.3 Feature Flagの例

// 完成していない機能をフラグで制御
const FEATURES = {
  newCheckout: false,  // まだ開発中
  darkMode: true       // リリース済み
};

function renderCheckout() {
  if (FEATURES.newCheckout) {
    return <NewCheckout />;
  }
  return <OldCheckout />;
}

5.4 TBDのメリット・デメリット

メリット

  • マージコンフリクトの最小化
  • 継続的インテグレーション(CI)に最適化
  • コード統合が頻繁で問題を早期発見

デメリット

  • 高度なテスト自動化が必要
  • Feature Flag管理の複雑さが増加
  • チームメンバーの高い能力と規律が必要

6. ブランチ戦略選択ガイド

6.1 プロジェクト規模別の推奨

プロジェクトタイプ 推奨戦略 理由
1-2人の小規模プロジェクト GitHub Flow シンプルで速い
スタートアップ(5-10人) GitHub Flow 素早いイテレーションとデプロイに適している
中規模チーム(10-30人) Git Flowまたは変形版 体系的なリリース管理が必要
大規模組織 Git FlowまたはTBD 明確なルールまたは強力な自動化が必要
オープンソースプロジェクト GitHub Flow 外部コントリビュータのPR処理に適している

6.2 デプロイ周期別の推奨

  • 毎日または随時デプロイ:GitHub Flow、TBD
  • 週次またはスプリント単位のデプロイ:GitHub Flow、Git Flow簡略版
  • 月次または四半期リリース:Git Flow

7. マージコンフリクトの解決

7.1 マージコンフリクトが発生する理由

2つのブランチで同じファイルの同じ部分を異なる形で修正した場合、Gitはどの変更を維持すべきか自分で判断できません。このときコンフリクト(conflict)が発生し、開発者が直接解決する必要があります。

7.2 コンフリクト解決の過程

# マージを試行
git merge feature/login
# CONFLICT (content): Merge conflict in src/App.js

# コンフリクトファイルを確認
git status

# コンフリクトファイルを開くと次のように表示される
# <<<<<<< HEAD
# const title = "Welcome";
# =======
# const title = "Hello World";
# >>>>>>> feature/login

コンフリクトマーカーを理解すると解決が簡単になります:

  • <<<<<<< HEAD:現在のブランチ(マージ先)の内容
  • =======:区切り線
  • >>>>>>> feature/login:マージしようとしているブランチの内容

7.3 コンフリクトの解決と完了

# 1. ファイルを直接編集して最終コードを作成
# コンフリクトマーカーをすべて削除し、希望するコードだけを残す

# 2. 解決したファイルをステージング
git add src/App.js

# 3. マージコミットを作成
git commit -m "Merge feature/login: resolve conflict in App.js"

# またはマージをキャンセル
git merge --abort

7.4 コンフリクト予防のヒント

  • 頻繁にpullして最新状態を維持
  • ブランチの寿命を短く維持
  • 大きなファイルより小さなファイル複数に分離
  • チームメンバーと作業領域を調整

8. Rebase vs Merge

8.1 Mergeの特徴

Mergeは2つのブランチの履歴をそのまま維持しながら統合します。

git switch main
git merge feature/login

メリット

  • 履歴が正確に保存される
  • 作業のコンテキストを理解しやすい
  • 安全で元に戻しやすい

デメリット

  • 履歴が複雑になる可能性
  • 不要なマージコミットが増える可能性

8.2 Rebaseの特徴

Rebaseはコミットを別のブランチの上に「再配置」します。最初からそのブランチで作業したかのような履歴が作られます。

# featureブランチでmainの最新内容の上に再配置
git switch feature/login
git rebase main

# mainでfast-forwardマージ
git switch main
git merge feature/login

メリット

  • きれいな線形履歴
  • 不要なマージコミットがない
  • コードレビュー時に変更を追跡しやすい

デメリット

  • 履歴が変更されるため注意が必要
  • すでにpushしたブランチには使用を控える
  • コンフリクト解決が複数回必要になる可能性

8.3 いつ何を使うか

状況 推奨
ローカルでのみ作業したブランチの整理 Rebase
すでにリモートにpushしたブランチ Merge
共有ブランチ(main、develop) Merge
featureブランチの最新化 Rebase(push前)
チームルールがある場合 チームルールに従う
黄金律:「公開(push)された履歴はrebaseしない。」他の人が基盤として使用中のコミットをrebaseすると大きな混乱が発生します。

おわりに:ブランチ戦略はチーム文化である

ここまで、ブランチの基本概念から様々なブランチ戦略、そしてコンフリクト解決方法まで見てきました。どの戦略が「正解」とは言い難いです。重要なのは、チームの状況に合った戦略を選択し、すべてのチームメンバーが同じルールに従うことです。

最初はシンプルなGitHub Flowから始めて、プロジェクトが大きくなるにつれて必要に応じてルールを追加していくのも良い方法です。ブランチ戦略は一度決めたら終わりではなく、チームとプロジェクトが成長するにつれて一緒に進化していくべきものです。

次回はPull Requestとコードレビューについて見ていきます。ブランチ戦略を実際に運用するにあたり、PRとコードレビューは必須要素ですので、ぜひ一緒に読んでみてください。