Git Flow、GitHub Flow、トランクベース開発: どの Git ワークフローを選ぶか
Git Flow は main と develop の2つの長期ブランチと、feature、release、hotfix の一時的なブランチを使うモデルで、計画的にバージョンを出すプロダクトに向いています。頻繁にデプロイするウェブサービスには、main から短いブランチを切って pull request を出す GitHub Flow か、feature フラグを使うトランクベース開発の方が一般的に扱いやすいです。
Git ワークフローとは何か、なぜ選択が重要か
Git ワークフローとは、チームでどのブランチを作り、どこから分岐し、どこへ統合し、何をリリース可能な状態とみなすかについての取り決めです。Git 自体はこれを強制しないため、取り決めがなければ各自が好きな方法で作業し、1か月後にはブランチが何十本も残り、何がデプロイされているのか分からなくなり、統合が長時間のコンフリクト解消になってしまいます。
代表的なモデルは、Git Flow、GitHub Flow(Feature Branch Workflow の一種)、トランクベース開発です。どれが「古く」「新しい」というものではありません。リリースの頻度、同時に保守するバージョンの数、自動テストの充実度など、状況に応じて使い分けるための道具です。
Git Flow: develop と release を持つモデル
Git Flow は 2010 年に Vincent Driessen が提唱しました。このモデルは2つの長期ブランチを基礎にします。
- main(古いプロジェクトでは master): リリース済みのコードだけを置きます。ここのコミットはそれぞれリリースに対応し、タグが付けられます。
- develop: 次のリリースに向けて、完成した機能を統合するブランチです。
さらに、一時的なブランチが3種類あります。
| ブランチ | 分岐元 | 統合先 | 目的 |
|---|---|---|---|
| feature/* | develop | develop | 新しい機能の開発 |
| release/* | develop | main と develop | バージョンの安定化: バグ修正、バージョン番号、ドキュメント |
| hotfix/* | main | main と develop | リリース済みバージョンの緊急修正 |
素の Git で Git Flow を行う
1つの機能とリリースの流れは次のとおりです。
# 機能
git switch develop
git switch -c feature/cart-discounts
# ... コミット ...
git switch develop
git merge --no-ff feature/cart-discounts
git branch -d feature/cart-discounts
# リリース
git switch -c release/1.4.0 develop
# ... バージョン番号の修正とバグ修正 ...
git switch main
git merge --no-ff release/1.4.0
git tag -a v1.4.0 -m "Release 1.4.0"
git switch develop
git merge --no-ff release/1.4.0
git branch -d release/1.4.0
--no-ff はこのモデルで重要です。早送りできる場合でもマージコミットを作るので、どのコミットがどの機能やリリースに属していたかを履歴で追えます。
git-flow 拡張
これらの手順をすべて手で入力しなくて済むように、git-flow というユーティリティがあります。現在は保守されているフォークを入れることが多く、パッケージマネージャーでは git-flow-avh という名前であることがよくあります。次のようなサブコマンドが追加されます。
git flow init -d
git flow feature start cart-discounts
git flow feature finish cart-discounts
git flow release start 1.4.0
git flow release finish 1.4.0
git flow hotfix start 1.4.1
git flow hotfix finish 1.4.1
git flow init はブランチ名とプレフィックスを尋ねます(-d を付けると既定値を使います)。finish コマンドは必要なマージをすべて実行し、タグを付け、一時的なブランチを削除します。多くの Git の GUI クライアントも、ボタン操作で Git Flow に対応しています。
Git Flow の長所と短所
長所は、構造が明確なことです。main はユーザーが使っているもの、develop は次のバージョンというように、コードの状態が分かりやすくなります。リリースを安定させるための独立した段階があり、hotfix の扱いも整理されています。アプリストアの審査を経たり、顧客の環境にインストールされたりするモバイルアプリ、パッケージソフトウェア、ライブラリ、ファームウェアには、よく合います。
短所は、ブランチと統合が多いことです。長く続く feature ブランチは develop との差が広がり、release と hotfix の二重の統合を忘れやすくなります。1日に何度もデプロイするウェブサービスでは、release ブランチが形式的な手続きになってしまいます。モデルの提唱者自身も 2020 年に、継続的に提供されるソフトウェアにはシンプルな方法、たとえば GitHub Flow を検討するよう補足しています。
GitHub Flow: 短いブランチと pull request
GitHub Flow は、Feature Branch Workflow を軽量にしたものです。ルールは数行で足ります。
- main は常に正常な状態で、デプロイできる。
- すべての作業は、main から分岐した、内容が分かる名前のブランチで行う。
- ブランチは定期的に push し、議論のために pull request(merge request)を作る。
- レビューと CI が緑になったら、ブランチを main に統合する。
- main に統合された変更は、すぐにデプロイされる。
git switch main
git pull
git switch -c feature/new-payment
# ... わかりやすいメッセージでコミット ...
git push -u origin feature/new-payment
# pull request を作成し、レビューと CI を通して main に統合
長所は、長期ブランチが1本だけで、ルールが最小限なことです。アイデアから本番環境までの道のりが短く、コードレビューが自然に組み込まれます。短所は、複数のバージョンの保守や、リリース前の安定化のための専用の場所がないことです。また、十分な自動テストがなければ「main は常に正常」は願望にとどまります。
追加の環境ブランチ(たとえば staging と production)を使う類似のアプローチは、GitLab Flow と呼ばれることもあります。デプロイが即座ではなく、定期的な実施や手動の確認を経て行われる場合に役立ちます。
トランクベース開発
トランクベース開発では、すべての開発者が1つのブランチ(トランク、つまり main)に、少なくとも1日1回は頻繁に変更を統合します。ブランチがあるとしても、寿命は数週間ではなく数時間です。完成していない機能は main に入りますが、feature フラグの背後に隠されます。
if (featureFlags.isEnabled("new-checkout", user)) {
renderNewCheckout();
} else {
renderOldCheckout();
}
最大の利点は、大きなコンフリクトがほとんど起きないことです。変更が小さく、全員が文脈を覚えているうちに統合されるからです。このモデルは継続的インテグレーションを文字どおり実現し、高速な CI と高いテストカバレッジを持つ成熟したチームに適しています。リリースブランチも使えますが、リリース直前にトランクから作り、修正は先にトランクに入れてから cherry-pick で移します。
短所は、規律と基盤が必要なことです。高速なテスト、フラグ、監視が欠かせません。新人にとっては毎日 main にコミットするのが怖いかもしれません。CI が弱いと、トランクは壊れた状態が続くブランチになってしまいます。フラグも適切な時期に削除しないと、不要な分岐が残ったままになります。
比較: Git Flow、GitHub Flow、トランクベース
| 比較項目 | Git Flow | GitHub Flow | トランクベース |
|---|---|---|---|
| 長期ブランチ | main と develop | main | main(トランク) |
| feature ブランチの寿命 | 数日から数週間 | 数日 | 数時間、またはブランチなし |
| リリースの頻度 | 計画的なバージョン | 統合のたびに | 継続的 |
| 複数バージョンの保守 | 可能(タグと hotfix) | 扱いにくい | release ブランチで可能 |
| CI とテストの要件 | 中程度 | 高い | 非常に高い |
| 大きなコンフリクトのリスク | 高い | 中程度 | 低い |
| 導入の敷居 | ルールの習得が必要 | 最小限 | 文化と feature フラグが必要 |
| 典型的なプロジェクト | モバイルアプリ、ライブラリ、パッケージソフト | ウェブサービス、オープンソース、スタートアップ | 頻繁にデプロイする大規模プロダクト |
チームに合うワークフローの選び方
次の質問に答えてみてください。
- リリース済みのバージョンを複数保守する必要があるか。 顧客が 2.x と 3.x を使っていて、両方に修正が必要なら、Git Flow か release ブランチを使うトランクベースが向いています。
- どのくらいの頻度でデプロイするか。 四半期に1回なら Git Flow でも問題ありません。毎日なら GitHub Flow かトランクベースを選びましょう。
- テストをどれだけ信頼できるか。 CI が遅く、カバレッジが低いなら、必須のレビューを伴う GitHub Flow から始め、徐々にブランチの寿命を短くしていきましょう。
- チームの規模と経験はどうか。 小さなチームや初心者には、「main は常に正常」という1つのルールと、すべてに pull request を使う GitHub Flow が最も簡単です。
実践的なアドバイスとして、「みんながやっているから」という理由で Git Flow を選ばないでください。まずは目的を満たす最もシンプルな方法から始め、安定化の段階や古いバージョンの保守など、具体的な問題が生じたときに複雑さを加えましょう。
どのワークフローにも共通するルール
- サーバー上で main を保護しましょう。直接の push を禁止し、統合の前に必須のレビューと緑の CI を求めます。
- ブランチの命名規則を決めましょう。
feature/、fix/、hotfix/と、タスク番号などを組み合わせます。 - ブランチは短く保ちましょう。長く生きたブランチほど統合が大変です。定期的に main を自分のブランチに merge または rebase で取り込んでください。
- pull request の統合方式(マージコミット、squash、rebase)を決め、一貫して使いましょう。
- リリースには、セマンティックバージョニングに従った注釈付きタグを付けましょう。
3つのモデルでのホットフィックス: 同じバグ、3通りの手順
それぞれの違いは、本番環境での緊急修正を見ると分かりやすくなります。
Git Flow では、main から hotfix/1.4.1 を作り、修正後、main にタグ v1.4.1 とともに統合し、さらに develop(またはそのときの release ブランチ)にも統合します。2つ目の統合を忘れるのは典型的なミスで、次のリリースでバグが「復活」します。
git switch -c hotfix/1.4.1 main
git commit -am "割引計算を修正"
git switch main && git merge --no-ff hotfix/1.4.1
git tag -a v1.4.1 -m "Hotfix 1.4.1"
git switch develop && git merge --no-ff hotfix/1.4.1
GitHub Flow では、ホットフィックスは main から切る通常の短いブランチで、レビューで優先されます。統合後は、通常の自動デプロイで本番に反映されます。特別な手続きはありません。
トランクベース では、まずトランクに修正をコミットします。本番で release ブランチが動いている場合は、git cherry-pick -x <ハッシュ> でそこに移します。-x は元のコミットへの参照をメッセージに加えるので、履歴でつながりが分かります。問題が新しい機能にある場合は、コードに手を加えず、feature フラグを無効にするだけで済むことも多いです。
面接で「どの Git ワークフローを使ったか」と聞かれたら
面接官が確かめたいのは名称の暗記ではなく、トレードオフの理解です。良い答えは、モデルの名前を挙げ、そこでブランチとレビューがどう働いていたかを説明し、なぜそのプロジェクトに合っていたかを述べることです。例: 「GitHub Flow を使っていました。main から分岐し、必須のレビューと CI を付けた pull request を出し、統合後は自動デプロイされます。週に数回リリースしていたので、Git Flow の release ブランチは遅れを生むだけでした。」さらに、プロセスが大きくなったら何を変えるかまで話せると評価されます。
まとめ
Git Flow は develop、release、hotfix のブランチを持つ厳密なモデルで、計画的なバージョンや複数のリリースの保守に向いています。GitHub Flow はよりシンプルで、ほとんどのウェブプロジェクトに合います。トランクベース開発は最高の速度を出せますが、成熟した CI と feature フラグが必要です。ワークフローは流行ではなく、リリースの頻度とテストの質に基づいて選んでください。3つのアプローチについて、それぞれのコマンドと典型的なミスを、Gitコースで実践的に扱っています。
よくある質問
Git Flow は古くなりましたか?
いいえ。ただし適用範囲は狭くなりました。継続的にデプロイするウェブサービスには過剰ですが、モバイルアプリ、ライブラリ、パッケージソフトでは今も使いやすいです。
リリースが頻繁なら develop ブランチは必要ですか?
通常は不要です。develop は main を重複させ、余計な統合を増やします。リリースが頻繁なら、main と短い feature ブランチだけで十分です。
Git Flow で rebase を使ってもいいですか?
自分だけが使う、まだ push していない feature ブランチに develop の内容を rebase で取り込むのは問題ありません。ただし、古典的なモデルでの develop と main への最終的な統合は、履歴の構造を保つために merge --no-ff で行います。
feature フラグは長い feature ブランチよりなぜ優れていますか?
コードが直ちに main に統合されるので、他のコードベースと差が開きません。機能を有効にするかどうかは別の判断になり、コードを戻さずに無効化できます。
Git Flow から GitHub Flow へはどう移行しますか?
進行中のリリースを完了させ、develop を main に統合し、main からデプロイするように CI を設定し直して、develop を削除します。以後の新しいブランチは main からのみ作成します。