本文へスキップ
webkida wiki
戻る

【Git】Git FlowとGitHub Flowの違い

main と develop を分ける流れと、main 一本で進める流れを並べ、出す頻度でどちらを選ぶかを整理する

ブランチの名前はチームごとに違うのに、会話では Git Flow と GitHub Flow がよく出てきます。作業の切り方だけ見ると、どちらも feature ブランチを切り、レビューしてから戻します。

分かれるのは、本番に届くまでに置く長期ブランチの本数です。Git Flow は main と develop の2本を置き、出す直前に release で固めます。GitHub Flow は main だけを置き、入った変更をそのまま出します。

見るのは3点です。どの線が本番か。feature はどこへ戻るか。出したあとの不具合を、どの線で直すか。ここが分かると、出す頻度に対してどちらが合うかまで判断できます。

用語

タグ

タグは、あるコミットを名前で指す印です。ブランチは先へ進みますが、タグは打った位置から動きません。

Git Flow では、main に戻したコミットへ v1.0 のように付けます。本番に出す中身は、このタグが指すコミットです。

デプロイ

デプロイは、そのコミットが本番環境で動くことです。ブランチを戻したあと、パイプラインがそのコミットを本番へ載せます。

リリース

リリースは、ユーザーがその機能を使えるようにすることです。Git Flow の release ブランチは、今出す版を固める線の名前です。ここでいうリリースは、その線のことではありません。

feature flag があるとき、デプロイは済んでいても、その機能のリリースはまだ、という状態があります。フラグをオンにしたときが、その機能のリリースです。フラグの置き方は 【Feature Flag】デプロイとリリースを分ける にあります。

作業ブランチはどちらも切る

どちらの流れでも、長期のブランチへ直接は積みません。変更は短い作業ブランチで作り、pull request で差分を見てから、元の線へ戻します。

戻す先は、図で feature が合流する本線です。Git Flow ではこの線が develop、GitHub Flow では main になります。戻す先の名前は違います。作業を一度分けてから戻す形は同じです。

gitGraph
   commit id: "本線"
   branch feature
   checkout feature
   commit id: "作業"
   checkout main
   merge feature id: "レビューして戻す"

図: 作業は本線から分かれ、レビューのあと本線に戻る。この本線が develop か main かは、流れごとに違う。

Git Flow

永続で残るブランチは、main と develop の2本です。feature、release、hotfix は、用が済めば消えます。

長期ブランチは main と develop の2本

main にあるものは、すでに本番へ出ている版です。main に新しいコミットが載るのは、版を出すときだけです。載ったコミットにはタグを打ち、そのコミットが本番の中身になります。

develop は、次に出す版の統合先です。機能はいったんここに集まります。develop 自体は本番へ出しません。

feature は develop に戻す

機能の作業は develop から切り、終わったら develop に戻します。この時点では main に届きません。本番の版はそのままです。

gitGraph
   commit id: "起点"
   branch develop
   checkout develop
   commit id: "次の版"
   branch feature
   checkout feature
   commit id: "機能"
   checkout develop
   merge feature id: "developへ戻す"

図: feature は develop から分かれ、develop に戻る。main にはまだ届かない。

release で固めてから出す

release を切るのは、今出す版のテストと、次の版へ向けた機能追加を同時に進めるためです。

develop のままテストすると、テスト中にも次の機能が同じ線に入ります。直したそばから中身が変わるので、この版として出すものが固まりません。release は、切った時点の develop を写した一時的な線です。ここでは不具合と版番号だけを直し、機能は足しません。そのあいだ develop には、次の版の機能を入れられます。

【release を切ったあと】develop

「機能Bは次の版なので、こちらに積む」

【同じ時間】release

「今出す版の不具合だけ直す。機能は足さない」

テストが終わったら、release を main に戻します。戻したコミットにタグを打ちます。本番へ出す中身は、このタグが指すコミットです。パイプラインがタグの push で動くか、main へのマージで動くかは、CI/CD の設計で決めます。

同じ release は develop にも戻します。release 上で直した不具合を、次の版に残すためです。

gitGraph
   commit id: "起点"
   branch develop
   checkout develop
   commit id: "機能A"
   branch release
   checkout release
   commit id: "不具合修正"
   checkout develop
   commit id: "機能B"
   checkout main
   merge release id: "v1.0" tag: "v1.0"
   checkout develop
   merge release id: "修正を戻す"

図: 機能Aまでを release に写し、不具合だけを直す。同じ時間に develop では機能Bが進む。整ったら main に戻して v1.0 を打ち、修正は develop にも戻す。

hotfix は両方に戻す

本番で急ぎの不具合が出たら、今の版と次の版の両方に修正を残します。main だけ直すと、次の release を develop から切ったときに、その修正が抜けます。

hotfix は、いま本番に出ているタグのコミットから切ります。develop からは切りません。次の版の機能が混ざるためです。hotfix 上で直して確認したら、main に戻してパッチのタグを打ちます。本番へ出す中身は、そのタグが指すコミットです。デプロイのきっかけは、release のときと同じで、CI/CD の設計次第です。

同じ hotfix は develop にも戻します。

gitGraph
   commit id: "v1.0" tag: "v1.0"
   branch develop
   checkout develop
   commit id: "次の版の機能"
   checkout main
   branch hotfix
   checkout hotfix
   commit id: "本番の修正"
   checkout main
   merge hotfix id: "v1.0.1" tag: "v1.0.1"
   checkout develop
   merge hotfix id: "developへ戻す"

図: hotfix は本番の v1.0 から切る。次の版の機能は入らない。v1.0.1 を main に打ち、同じ修正を develop にも戻す。

向く出し方

出す日が決まっていて、版を固めてから本番へ出すときに向きます。テストのあいだ次の版の開発が続くなら、release がその重なりを受け持ちます。

重ならなくても、定期的に版を固めて出すなら同じ形です。本番の線は main の1本で、出した版はタグで残ります。

GitHub Flow

原則は、main がいつでも本番に出せることです。ブランチの形は、ここから決まっています。

永続で残るブランチは main だけです。develop も、版を固める release も、hotfix 専用の線も置きません。

長期ブランチは main だけ

いつでも出せるなら、本番を壊す未完成は main に置けません。main に戻ったものは、本番で動いてよいものだけです。

次の版を溜める本線は要りません。溜める場所を置くと、main とは別に、まだ出せない変更の線ができます。この形は、main を常にデプロイできる状態に保ち、戻したものを頻繁に出す前提です。版を固めてから出す運用では、固める線が要ります。次の版の開発と重なっていなくても、定期リリースなら同じです。

feature は短く、main に戻す

機能の作業は main から切ります。ブランチは短く切り、レビューが済んだら main に戻します。

大きい機能は、ユーザーに届くところまで小さく完結する単位に分けます。単位ができるたびに main へ戻すので、作業ブランチはそこで終わります。戻した時点でデプロイされ、同時にリリースになります。

feature flag がないときは、見せられる単位だけを戻します。まだ見せられない残りは、次の単位ができるまで作業ブランチに置きます。

gitGraph
   commit id: "本番"
   branch feature
   checkout feature
   commit id: "機能"
   checkout main
   merge feature id: "mainへ戻す"

図: feature は main から分かれ、レビューのあと main に戻る。戻したコミットが、次の本番になる。

feature flag があるときは、コードを main に戻すことと、ユーザーに見せることを分けられます。コードは本番で動きますが、フラグはオフです。既存の動きは壊れていません。見せると決めたとき、ブランチを切り直さず、フラグをオンにします。オンにしたときが、その機能のリリースです。値の読み方は 【Feature Flag】デプロイとリリースを分ける にあります。

【main に戻したあと】本番

「このコミットは動いている。新しい機能のフラグはオフだ」

【見せると決めたとき】

「フラグをオンにする。ブランチは切り直さない」

sequenceDiagram
    participant Dev as 開発者
    participant Prod as 本番
    participant User as ユーザー

    Dev->>Prod: ① main に戻してデプロイ
    Note over Prod: ② フラグはオフ<br/>ユーザーには見せない
    Dev->>Prod: ③ フラグをオン
    Prod-->>User: ④ ここでリリース

図: フラグがあるときは、デプロイしたあとも機能はオフのまま。オンにしたときがリリース。

デプロイは main に入ったあと

main に戻ったものは、本番へ出せます。確認を先にしたいときは、マージ前にその作業ブランチを出して確かめます。確かめているあいだに main が進むことも、マージで新しいコミットができることもあります。戻した main は、確認したブランチそのものとは限りません。マージ後の main も CI で確認してから、本番へ出します。

タグの push で出すか、main へのマージで出すかは、CI/CD の設計です。どちらのきっかけでも、main をいつでも出せる状態に保つ点は同じです。

本番の修正も同じ一本

本番の修正も、機能追加と同じ形です。main から切り、main に戻します。戻り先は main だけです。戻した修正は、今の本番にも、このあとに続く変更にも入ります。

gitGraph
   commit id: "本番"
   branch feature
   checkout feature
   commit id: "機能"
   checkout main
   merge feature id: "機能を戻す"
   branch fix
   checkout fix
   commit id: "本番の修正"
   checkout main
   merge fix id: "修正を戻す"

図: 機能追加も本番の修正も、main から切って main に戻る。別の戻り先はない。

向く出し方

main を常にデプロイできる状態に保ち、戻したものを頻繁に出すときに向きます。

まだ見せない機能は、見せられる単位に分けて戻すか、フラグをオフにして main に載せます。

並べるとどこが違うか

違いは、永続ブランチの本数と、本番に届くタイミングです。

Git FlowGitHub Flow
永続ブランチmain と developmain だけ
featuredevelop から切り、develop に戻すmain から切り、main に戻す
版を固める間release でテストし、develop は次の版を進める固める線は置かない
本番の修正main と develop の両方に戻すmain に戻す。機能追加と同じ
まだ見せないもの本番の main には載せない。次の版は develop に置く見せられる単位に分けて戻す。フラグがあれば未公開のまま main に載せる
本番へ出す中身main に戻したコミット。タグで指すmain に戻したコミット

Git Flow は、今の版と次の版を別の線に置きます。release のあいだも develop は動き、hotfix は両方に戻します。

GitHub Flow は、本番と次の統合先を main の1本にします。戻したものは出せる状態です。まだ見せない機能は、見せられる単位に分けて戻すか、フラグをオフにしてデプロイとリリースを分けます。

どちらの流れでも、デプロイのきっかけは CI/CD の設計です。タグの push か、main へのマージかは、ブランチの形とは別に決めます。

どちらを選ぶか

main を常にデプロイできる状態に保ち、戻したものを頻繁に出すなら、GitHub Flow です。まだ見せない機能は、見せられる単位に分けて戻すか、フラグでデプロイとリリースを分けます。

版を固めてから本番へ出すなら、Git Flow です。テストと次の版の開発が重なるときは、release がその重なりを受け持ちます。重ならなくても、定期的に版を固めて出すなら、固める線は同じように要ります。

sequenceDiagram
    actor U as あなた
    participant Q as 出し方

    U->>Q: ① main を常に出せる状態に保ち、頻繁に出すか
    alt はい
        Q-->>U: GitHub Flow<br/>main だけ
    else いいえ
        Q-->>U: Git Flow<br/>版を固めてから出す
    end

図: 頻繁に出すなら GitHub Flow。版を固めてから出すなら Git Flow。次の版の開発と重なっていなくても、定期リリースなら Git Flow。

まとめ

永続ブランチは、Git Flow が main と develop の2本、GitHub Flow が main の1本です。

Git Flow では、release で今の版をテストしながら、develop で次の版を進めます。本番へ出すのは、main に戻してタグを打ったコミットです。本番の修正は、今の版と次の版の両方に戻します。

GitHub Flow では、main をいつでも出せる状態に保ち、戻したものを頻繁に出します。機能追加も本番の修正も、見せられる単位で main に戻します。

フラグがあれば、デプロイしたあとに、その機能のリリースを分けられます。マージ後の main は、確認した作業ブランチそのものとは限らないので、CI で確かめてから本番へ出します。


この記事をシェア:

前の記事
【Feature Flag】デプロイとリリースを分ける
次の記事
【Search Console】初回設定でハマったサイトマップとインデックス