Gitブランチ戦略を実践

intermediate | 120分 で読める | 2025.12.02

このチュートリアルで学ぶこと

  • ブランチの基本操作
  • Feature Branch Workflow
  • Git FlowとGitHub Flowの違い
  • マージとリベースの使い分け
  • コンフリクトの解決

ブランチ戦略とは?なぜ重要なのか

ブランチ戦略の歴史

ブランチ戦略が注目されるようになったのは、チーム開発が複雑化した2000年代後半からです。

2010年Vincent Driessenが「A successful Git branching model」という記事でGit Flowを提唱。これが最初の体系的なブランチ戦略として広く普及しました。

その後、GitHubが2011年にシンプルなGitHub Flowを提唱。継続的デプロイを行うチームに最適なモデルとして支持を集めました。

「ブランチ戦略は、チームのワークフローに合わせて選択すべきもの。万能な戦略は存在しない」— Vincent Driessen, 2020年の補足記事より

なぜブランチ戦略が必要なのか

  1. 並行開発: 複数の機能を同時に開発できる
  2. リスク分離: 不安定なコードをメインラインから隔離
  3. コードレビュー: プルリクエストによる品質担保
  4. リリース管理: 本番環境への反映をコントロール

主要なブランチ戦略の比較

戦略複雑さ適したチームデプロイ頻度
Feature Branch小規模任意
GitHub Flow継続的デプロイ毎日〜週数回
Git Flowリリースサイクルが明確週〜月1回
Trunk Based大規模・成熟したチーム毎日〜複数回/日

ブランチの基本操作

ブランチの作成と切り替え

# ブランチ一覧を表示
git branch

# リモートブランチも含めて表示
git branch -a

# 新しいブランチを作成
git branch feature/login

# ブランチを切り替え
git checkout feature/login

# 作成と切り替えを同時に(推奨)
git checkout -b feature/login

# Git 2.23以降の新しいコマンド(推奨)
git switch -c feature/login
git switch feature/login

公式ドキュメント: git-branch

ブランチの命名規則

チームで一貫した命名規則を使うことが重要です:

# 機能開発
feature/user-authentication
feature/payment-integration

# バグ修正
fix/login-button-crash
bugfix/memory-leak

# 緊急修正
hotfix/security-vulnerability

# リリース準備
release/v1.2.0

# 実験的な機能
experiment/new-algorithm

ベストプラクティス: ブランチ名は小文字、ハイフン区切り、課題番号を含めると追跡しやすい(例: feature/JIRA-123-add-login

リモートブランチの操作

# リモートブランチを含めて表示
git branch -a

# リモートブランチをローカルにチェックアウト
git checkout -b feature/login origin/feature/login

# または(Git 2.23以降)
git switch feature/login  # 自動的にリモート追跡

# ブランチをリモートにプッシュ
git push -u origin feature/login

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

# ローカルブランチを削除
git branch -d feature/login

# マージされていないブランチを強制削除
git branch -D feature/login

ブランチの状態確認

# ブランチ間の差分を確認
git diff main..feature/login

# マージ済みのブランチを表示
git branch --merged

# 未マージのブランチを表示
git branch --no-merged

# ブランチの最後のコミットを表示
git branch -v

Feature Branch Workflow

最も基本的なブランチ戦略です。機能ごとにブランチを作成し、完了後にメインブランチにマージします。

ワークフロー図

gitGraph
    commit
    branch feature/A
    commit
    commit
    commit
    commit
    checkout main
    merge feature/A
    commit

実践シナリオ: ログイン機能の追加

# 1. メインブランチを最新に
git checkout main
git pull origin main

# 2. 機能ブランチを作成
git checkout -b feature/login

# 3. 実装とコミット
# (コードを編集)
git add .
git commit -m "feat: Add login form component"

# (さらに実装)
git add .
git commit -m "feat: Add login API integration"

# (テスト追加)
git add .
git commit -m "test: Add login validation tests"

# 4. リモートにプッシュ
git push -u origin feature/login

# 5. プルリクエストを作成(GitHub上で)

# 6. レビュー後、マージ

プルリクエストのベストプラクティス

「プルリクエストは小さく保つ。レビュアーが20分以内に確認できるサイズが理想」— Google Engineering Practices

  1. 適切なサイズ: 200-400行が目安
  2. 単一の目的: 1つのPRに1つの機能/修正
  3. 説明を丁寧に: 背景、変更内容、テスト方法を記載
  4. セルフレビュー: 提出前に自分でチェック

Git Flow

リリースサイクルが明確なプロジェクト向けの戦略です。Vincent Driessenが2010年に提唱しました。

主要ブランチ

flowchart TB
    main["main(またはmaster)"]
    develop["develop(開発統合ブランチ)"]
    feature["feature/*(機能開発)"]
    release["release/*(リリース準備)"]
    hotfix["hotfix/*(緊急バグ修正)"]

    main --> develop
    develop --> feature
    develop --> release
    main --> hotfix
ブランチ目的派生元マージ先
main本番リリース--
develop開発統合mainmain, release
feature/*機能開発developdevelop
release/*リリース準備developmain, develop
hotfix/*緊急修正mainmain, develop

Git Flowの実践

# developから機能ブランチを作成
git checkout develop
git checkout -b feature/user-profile

# 機能完了後、developにマージ
git checkout develop
git merge --no-ff feature/user-profile
git branch -d feature/user-profile

# リリース準備
git checkout -b release/1.0.0 develop

# バージョン番号更新、バグ修正など
git commit -m "chore: Bump version to 1.0.0"

# リリース完了
git checkout main
git merge --no-ff release/1.0.0
git tag -a v1.0.0 -m "Version 1.0.0"

git checkout develop
git merge --no-ff release/1.0.0
git branch -d release/1.0.0

# 緊急修正(Hotfix)
git checkout main
git checkout -b hotfix/security-fix

# 修正後
git checkout main
git merge --no-ff hotfix/security-fix
git tag -a v1.0.1 -m "Security patch"

git checkout develop
git merge --no-ff hotfix/security-fix
git branch -d hotfix/security-fix

git-flowツール

git-flowコマンドを使うと操作が簡単になります:

# インストール
# macOS
brew install git-flow

# Ubuntu
apt install git-flow

# 初期化
git flow init

# 機能開発
git flow feature start user-profile
git flow feature finish user-profile

# リリース
git flow release start 1.0.0
git flow release finish 1.0.0

# ホットフィックス
git flow hotfix start security-fix
git flow hotfix finish security-fix

Git Flowの適用シーン

適している場合:

  • 定期的なリリースサイクルがある
  • 複数バージョンのサポートが必要
  • QAチームがある

適さない場合:

  • 継続的デプロイを行っている
  • 小規模チーム
  • Webアプリで常に最新版のみ運用

Vincent Driessenの2020年の補足: 「Web開発のように継続的デプロイが一般的になった今、Git Flowは多くのプロジェクトに過剰。GitHub Flowなどシンプルなモデルを検討してほしい」

GitHub Flow

シンプルで継続的デプロイに適した戦略です。GitHubが公式に推奨しています。

ワークフロー図

gitGraph
    commit
    branch pr-1
    commit
    commit
    commit
    checkout main
    merge pr-1
    branch pr-2
    commit
    commit
    commit
    checkout main
    merge pr-2
    commit

6つのルール

  1. mainブランチは常にデプロイ可能
  2. 機能開発はmainから分岐
  3. 定期的にリモートにプッシュ
  4. プルリクエストでコードレビュー
  5. レビュー後、mainにマージ
  6. マージ後すぐにデプロイ

GitHub公式ブログ: GitHub Flow

GitHub Flowの実践

# mainから機能ブランチを作成
git checkout main
git pull origin main
git checkout -b add-dark-mode

# 開発・コミット(小さく頻繁に)
git add .
git commit -m "feat: Add dark mode toggle"
git push -u origin add-dark-mode

# プルリクエストを作成(GitHub上)
# コードレビュー
# CI/CDパイプラインが自動実行

# PR承認後、マージ & デプロイ
# マージ後、ブランチを削除
git checkout main
git pull origin main
git branch -d add-dark-mode

GitHub Flowの適用シーン

適している場合:

  • 継続的デプロイを行っている
  • 常に最新版のみを運用
  • 小〜中規模チーム

Trunk Based Development

GoogleやFacebookなど大規模チームで採用されている戦略です。

特徴

  • mainブランチ(trunk)に直接、または短命なブランチからマージ
  • ブランチは1-2日以内にマージ
  • 大きな機能はフィーチャーフラグで制御
gitGraph
    commit
    branch short-1
    commit
    checkout main
    merge short-1
    branch short-2
    commit
    checkout main
    merge short-2
    branch short-3
    commit
    checkout main
    merge short-3
    commit

参考: trunkbaseddevelopment.com

マージ vs リベース

マージ(Merge)

履歴を保持し、マージコミットを作成します。

# feature/loginをmainにマージ
git checkout main
git merge feature/login

# マージコミットを必ず作成(--no-ff)
git merge --no-ff feature/login

結果:

gitGraph
    commit
    branch feature
    commit
    commit
    checkout main
    merge feature

リベース(Rebase)

履歴を直線的に書き換えます。

# mainの最新をfeatureブランチに取り込む
git checkout feature/login
git rebase main

# インタラクティブリベース(コミット整理)
git rebase -i HEAD~3

結果(リベース後):

  • mainの最新コミットの後ろにfeatureのコミットが直線的に並ぶ
  • マージコミットは作成されない

どちらを使うべきか?

シナリオ推奨理由
共有ブランチへの統合マージ履歴を保持、安全
ローカルのコミット整理リベースきれいな履歴
mainの最新をfeatureに取り込むリベース線形な履歴
プッシュ済みコミットマージのみ履歴の書き換えは危険

黄金律: 「他の人と共有しているコミットは絶対にリベースしない」

インタラクティブリベースでコミットを整理

git rebase -i HEAD~3

エディタが開きます:

pick abc1234 WIP: 作業中
pick def5678 fix: typo
pick ghi9012 feat: ログイン機能追加

# Commands:
# p, pick = コミットを使う
# r, reword = メッセージを編集
# s, squash = 前のコミットと統合
# f, fixup = 前のコミットと統合(メッセージは捨てる)
# d, drop = コミットを削除
# コミットを整理
pick abc1234 WIP: 作業中
squash def5678 fix: typo
squash ghi9012 feat: ログイン機能追加

コンフリクトの解決

コンフリクトが発生する仕組み

flowchart TB
    Original["main: Hello World"]
    OtherMerge["Hello Everyone<br/>(別の人がマージ)"]
    YourChange["feature: Hello Universe<br/>(あなたの変更)"]
    Conflict["コンフリクト発生!"]

    Original --> OtherMerge
    Original --> YourChange
    OtherMerge --> Conflict
    YourChange --> Conflict

コンフリクトの解決手順

# マージ中にコンフリクトが発生した場合
git status  # コンフリクトファイルを確認

# ファイルを編集してコンフリクトを解決

コンフリクトのマーカー:

<<<<<<< HEAD
現在のブランチの内容
=======
マージしようとしているブランチの内容
>>>>>>> feature/login

解決後:

# コンフリクトを解決したファイルをステージング
git add conflicted-file.js

# マージを完了
git commit -m "Merge feature/login with conflict resolution"

# または、マージを中止する場合
git merge --abort

コンフリクト解決のベストプラクティス

  1. こまめにmainをマージ/リベース: コンフリクトを小さく保つ
  2. コミュニケーション: 同じファイルを編集する場合は事前に相談
  3. ツールを活用: VS Code、GitKrakenなどのGUIツール
  4. テストを実行: 解決後は必ずテストを通す

VS Codeでのコンフリクト解決

VS Codeはコンフリクトを視覚的に解決できます:

Accept Current Change  | Accept Incoming Change  | Accept Both Changes

実践: チーム開発シミュレーション

2人の開発者がコンフリクトを経験するシナリオを再現します。

# 1. リポジトリを初期化
mkdir team-dev-simulation
cd team-dev-simulation
git init
echo "# Team Project" > README.md
git add README.md
git commit -m "Initial commit"

# 2. 開発者Aのブランチ
git checkout -b feature/header
echo "<header>Header A</header>" > index.html
git add index.html
git commit -m "feat: Add header by Dev A"

# 3. mainに戻って開発者Bのブランチ
git checkout main
git checkout -b feature/footer
echo "<footer>Footer B</footer>" > index.html
git add index.html
git commit -m "feat: Add footer by Dev B"

# 4. feature/headerを先にマージ
git checkout main
git merge feature/header

# 5. feature/footerをマージ(コンフリクト発生!)
git merge feature/footer
# CONFLICT (add/add): Merge conflict in index.html

# 6. コンフリクトを解決
# index.htmlを編集して両方の変更を含める
cat > index.html << 'EOF'
<header>Header A</header>
<footer>Footer B</footer>
EOF

git add index.html
git commit -m "merge: Resolve conflict between header and footer"

ブランチ戦略の選択ガイド

質問に答えてフローを選択

  1. 継続的にデプロイしますか?

    • はい → GitHub Flow または Trunk Based
    • いいえ → Git Flow を検討
  2. リリースサイクルは?

    • 毎日〜週数回 → GitHub Flow
    • 週1回〜月1回 → Git Flow
    • 1日に複数回 → Trunk Based
  3. チームサイズは?

    • 1-5人 → GitHub Flow
    • 5-20人 → GitHub Flow または Git Flow
    • 20人以上 → Trunk Based(フィーチャーフラグ必須)

よくある間違いとアンチパターン

1. 長寿命ブランチ

# アンチパターン: 数週間マージされないブランチ
# コンフリクトが巨大になり、マージが困難に

# ベストプラクティス: こまめにマージ
git checkout feature/big-feature
git fetch origin
git rebase origin/main  # 毎日実行

2. プッシュ後のリベース

# 危険!共有されたコミットの書き換え
git push origin feature/x
git rebase -i HEAD~3
git push --force  # 他の人の変更を上書き

# 安全: force-with-leaseを使う
git push --force-with-lease

3. mainへの直接コミット

# アンチパターン
git checkout main
git commit -m "Quick fix"

# ベストプラクティス: 必ずPRを通す
git checkout -b fix/quick-fix
git commit -m "Quick fix"
git push -u origin fix/quick-fix
# PRを作成

参考リンク

公式ドキュメント・原典

ツール

関連記事・書籍

← 一覧に戻る