Git FlowとGitHub Flowの違い:小さなチームはどちらで回すか

公開 書いた人 大林 諒

外注先から「うちはGit Flowです」「developに向けてプルリクエストを出してください」と言われて、何のことか分からなかった人向けの話です。Git FlowもGitHub Flowも、Gitの機能ではありません。枝(ブランチ)をどう分けて、いつ合流させるかの決めごとです。サンプル料理教室のホームページを例に、同じ変更を2つのやり方で実際に動かして比べます。読み終わると、自分の会社がどの決めごとで回せばいいかを選べて、外注先の話にも付いていけます。

この記事の内容
  1. 先に答えると
  2. 2つを比べる
  3. Git Flowの枝
  4. 原典の著者が後から書いた注記
  5. git flowコマンドの現状
  6. 普通のgitでGit Flowを動かす
  7. 同じ変更をGitHub Flowで動かす
  8. 料理教室ならどれで回すか
  9. 小さな会社で採用しなくていい理由
  10. 決めごとを仕組みで止める
  11. Git FlowからGitHub Flowへ移す
  12. できないことと、その代わり
  13. よく詰まるところ
  14. 次に読む

先に答えると

Git Flowは main develop に加えて機能・リリース準備・緊急修正の枝を使う、版番号を付けて出す製品向けの型です。GitHub Flowは main と短い作業の枝だけで回す型です。小さな会社のホームページや社内のスクリプトなら、GitHub Flowで足ります。

  • どちらも決めごとで、Gitに設定する機能ではありません
  • 一人で直しているなら main だけで十分です
  • 数人で触るならGitHub Flowにします
  • 同じものを版ごとに分けて配り、古い版も面倒を見るならGit Flowを考えます
  • Git Flowの提案者自身が、Webアプリのように更新を出し続けるものにはもっと単純な型を勧めています

2つを比べる

GitHub FlowGit Flow
残し続ける枝main の1本main と develop の2本
一時的な枝作業の枝1種類機能、リリース準備、緊急修正の3種類
向いているもの更新をすぐ出すサイトやツール版番号を付けて出す製品、複数の版を保守する製品
リリースの仕方main に入ったものを出すリリース準備の枝を作り、main に入れて版番号の印を付ける
人数の目安一人から始められる版の管理を決めて守れる人がいるチーム
覚えること枝を切る、プルリクエスト、合流、枝を消す左の4つに加えて、枝ごとの作り元と合流先、印の付け方

人数の行は決まりではなく、実際に運用したうえでの目安です。プルリクエスト(Pull Request、PR)は、枝を本筋に入れる前に見てもらう依頼です。

GitLab Flowという名前を聞くこともあります。GitLabが紹介している型で、Git Flowより単純な代案という位置づけです。main に入れてから、必要に応じて production のような本番用の枝へ流します。本番の前に検証の環境を挟みたいときの考え方です。実際に運用していると、考え方だけならGitHubを使っていても借りられます。GitHubで使えるかどうかは、GitLabの説明には書かれていません。

GitHub Flow と Git Flow を同じ縮尺で並べ、枝の数と戻り先の違いを見る図
GitHub Flow と Git Flow を同じ縮尺で並べ、枝の数と戻り先の違いを見る図

Git Flowの枝

Git Flowは2010年に Vincent Driessen が自分のサイトで公開した型です。原典では本筋の枝の名前が master ですが、今のGitHubに合わせて main と読み替えます。

枝役割作り元合流先
main本番に出ている版。合流のたびに版番号の印を付ける残し続ける残し続ける
develop次の版を集める場所残し続ける残し続ける
機能の枝(feature)機能を1つ作るdevelopdevelop
リリース準備の枝(release)出す直前の版番号の更新や小さな直し。新しい機能は入れないdevelopmain と develop
緊急修正の枝(hotfix)本番の不具合をすぐ直すmainmain と develop

リリース準備の枝があるあいだは、緊急修正の枝の合流先は develop ではなく、そのリリース準備の枝です。

枝の名前は、原典の例にならって release-1.1 hotfix-1.1.1 とします。機能の枝の名前は add-summer-class です。

原典の著者が後から書いた注記

原典の冒頭には、2020年3月5日付けの注記(Note of reflection)が足されています。趣旨は次のとおりです。

  • この型を考えたのは2010年で、その後に広まり、標準や教義のように扱われることもある
  • その間に、継続して更新を出すWebアプリが主流の用途になった。Webアプリは複数の版を並べて保守することがほとんどない
  • 継続して出すソフトなら、GitHub Flowのようなもっと単純な型を勧める
  • 版番号を明示して出すソフトや、複数の版を保守するソフトなら、今でも合うかもしれない

つまり提案した本人が、更新を出し続けるWebアプリには別の型を勧めています。外注先に「Git Flowが標準です」と言われたときは、この注記を知っておくと話がしやすくなります。

git flowコマンドの現状

検索すると git flow init や git flow feature start というコマンドが出てきますが、これはGit本体の機能ではなく、別に入れる拡張です。Gitだけの状態で打つと、次のように出ます。

$ git flow
git: 'flow' is not a git command. See 'git --help'.

2026年11月時点の状況は次のとおりです。

拡張状況
nvie/gitflow(最初の拡張)2025年10月14日にアーカイブ。READMEに「no longer maintained」とあり、git-flow-next を案内している
gitflow-avh(その派生)2023年6月19日にアーカイブ
Homebrewの git-flow非推奨。2026年12月19日に使えなくなる予定
git-flow-nextTowerが提供している後継

古い拡張の手順をそのまま入れないでください。普通の git だけで同じことができるので、次の節はそれで動かします。

普通のgitでGit Flowを動かす

ここからの表示は実際に動かしたものです。GitHubの代わりに、手元のフォルダに練習用の送り先を作って試しました。そのため送り先がフォルダの形で出ます。main に「最初の版」のコミット(変更を1回分の記録として残したもの)がある状態から始めます。

developを作る

$ git switch -c develop
Switched to a new branch 'develop'

$ git push -u origin develop
To ../remote/website.git
 * [new branch]      develop -> develop
branch 'develop' set up to track 'origin/develop'.

機能の枝で夏の教室を足す

$ git switch -c add-summer-class develop
Switched to a new branch 'add-summer-class'

$ git commit -m "夏の教室を追加"
[add-summer-class 6152978] 夏の教室を追加
 1 file changed, 1 insertion(+)

$ git switch develop
Switched to branch 'develop'
Your branch is up to date with 'origin/develop'.

$ git merge --no-ff add-summer-class
Merge made by the 'ort' strategy.
 index.html | 1 +
 1 file changed, 1 insertion(+)

$ git branch -d add-summer-class
Deleted branch add-summer-class (was 6152978).

--no-ff は、合流の記録(マージコミット)を必ず残す指定です。原典はこの指定を使います。--no-ff を付けない場合で、合流先が動いていなければ、次のように枝の区切りが履歴に残りません。

$ git merge add-summer-class
Updating 6a7d855..52ef075
Fast-forward
 index.html | 1 +
 1 file changed, 1 insertion(+)

$ git log --oneline --graph
* 52ef075 夏の教室を追加
* 6a7d855 最初の版

リリース準備の枝から出す

develop からリリース準備の枝を作り、版番号を更新して、main と develop の両方へ戻します。git tag は版番号の印を付ける操作です。

$ git switch -c release-1.1 develop
Switched to a new branch 'release-1.1'

$ git commit -m "版番号を1.1にする"
[release-1.1 ce9d457] 版番号を1.1にする
 1 file changed, 1 insertion(+), 1 deletion(-)

$ git switch main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.

$ git merge --no-ff release-1.1
Merge made by the 'ort' strategy.
 VERSION    | 2 +-
 index.html | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

$ git tag -a 1.1 -m "1.1"

$ git switch develop
Switched to branch 'develop'
Your branch is ahead of 'origin/develop' by 2 commits.
  (use "git push" to publish your local commits)

$ git merge --no-ff release-1.1
Merge made by the 'ort' strategy.
 VERSION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

$ git branch -d release-1.1
Deleted branch release-1.1 (was ce9d457).

緊急修正の枝で直す

本番の電話番号が間違っていた場面です。develop ではなく main から枝を作ります。流れはリリース準備の枝と同じで、最後に両方へ戻します。

$ git switch -c hotfix-1.1.1 main
Switched to a new branch 'hotfix-1.1.1'

$ git commit -m "問い合わせの電話番号を修正"
[hotfix-1.1.1 491d78d] 問い合わせの電話番号を修正
 2 files changed, 2 insertions(+), 2 deletions(-)

$ git switch main
Switched to branch 'main'
Your branch is ahead of 'origin/main' by 4 commits.
  (use "git push" to publish your local commits)

$ git merge --no-ff hotfix-1.1.1
Merge made by the 'ort' strategy.
 VERSION    | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

$ git tag -a 1.1.1 -m "1.1.1"

$ git switch develop
Switched to branch 'develop'
Your branch is ahead of 'origin/develop' by 4 commits.
  (use "git push" to publish your local commits)

$ git merge --no-ff hotfix-1.1.1
Merge made by the 'ort' strategy.
 VERSION    | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

$ git branch -d hotfix-1.1.1
Deleted branch hotfix-1.1.1 (was 491d78d).

$ git push origin main develop --tags
To ../remote/website.git
   3c84094..a062ed0  develop -> develop
   3c84094..62c3102  main -> main
 * [new tag]         1.1 -> 1.1
 * [new tag]         1.1.1 -> 1.1.1

履歴の図はこうなりました。

$ git log --oneline --graph --all --decorate
*   a062ed0 (HEAD -> develop, origin/develop) Merge branch 'hotfix-1.1.1' into develop
|\  
* \   c26ad3c Merge branch 'release-1.1' into develop
|\ \  
| | | *   62c3102 (tag: 1.1.1, origin/main, main) Merge branch 'hotfix-1.1.1'
| | | |\  
| | | |/  
| | |/|   
| | * | 491d78d 問い合わせの電話番号を修正
| | |/  
| | *   902124d (tag: 1.1) Merge branch 'release-1.1'
| | |\  
| | |/  
| |/|   
| * | ce9d457 版番号を1.1にする
|/ /  
* |   4155709 Merge branch 'add-summer-class' into develop
|\ \  
| |/  
|/|   
| * 6152978 夏の教室を追加
|/  
* 3c84094 (tag: 1.0) 最初の版

同じ変更をGitHub Flowで動かす

夏の教室の追加と電話番号の修正を、GitHub Flowでやります。本物のGitHubならプルリクエストでマージするところを、ここでは手元で合流させました。手順の詳しい話は「git branchとmergeの使い方:枝を分けて合流する、GitHub Flowまで」と「プルリクエストとは:作り方・レビュー・マージの流れ」にあります。

$ git log --oneline --graph --all --decorate
*   ffe6e10 (HEAD -> main, origin/main) Merge branch 'fix-phone-number'
|\  
| * b9d2b2f 問い合わせの電話番号を修正
|/  
*   f6fe047 Merge branch 'add-summer-class'
|\  
| * 974932c 夏の教室を追加
|/  
* c730821 最初の版

同じ2件を出すのに、Git Flowは合流のコミットが5つ、GitHub Flowは2つでした。

$ git rev-list --count --merges main develop
5

$ git rev-list --count --merges main
2

料理教室ならどれで回すか

状況選ぶものやること
代表が一人で料金表を直しているmain だけ枝を切らずにコミットして送る
代表と外注エンジニアBの2人で website を触るGitHub Flow枝を切ってプルリクエストにし、確かめてから main へ
代表がAIに大きな変更をさせるGitHub Flow枝の上でやらせ、気に入らなければ枝ごと捨てる
reservation-mail を他の教室にも配り、1.0と1.1の両方を直し続けるGit Flowを考える版ごとの印と、古い版の修正の流れが要る

サイト1つとスクリプト1つの会社は、1行目か2行目です。一人の場合はこうなります。

$ git commit -m "夏の教室を追加"
[main 4fcab4d] 夏の教室を追加
 1 file changed, 1 insertion(+)

$ git log --oneline
4fcab4d 夏の教室を追加
87cbd0d 最初の版

小さな会社で採用しなくていい理由

小さな会社でGit Flowを採用する必要は、ほぼありません。理由は次の3つです。

  • ホームページの古い版を保守する人はいません。公開中の版が1つだけなら、develop と main を分ける理由が薄くなります
  • 枝の作り元と合流先を間違えると、修正が片方に入りません。枝の数だけ間違える場所が増えます
  • 枝を守るのは人です。人数が少ないほど、決めごとを見張る余裕がありません

GitLab Docsにも「Don’t implement a strategy that is more complex than your product needs.」(製品に必要な以上に複雑な戦略にしない)とあります。

外注先がすでにGit Flowで動かしているなら、無理に変えさせる話でもありません。そのリポジトリの流れに合わせて、プルリクエストの送り先だけ確かめます。

決めごとを仕組みで止める

ここまでの話はどれも約束なので、守らなくてもGitは止めません。main への直接のpushを止め、必須レビューを付けるのが枝の保護で、これはGitHubの機能です。ただし、公式のプラン一覧では、枝の保護と必須レビューはTeamの「非公開リポジトリの高度な機能」に載っていて、FreeのOrganization(GitHub上の会社のアカウント)の一覧にはありません。Freeの非公開リポジトリでは使えないものとして扱います(2026年11月時点)。設定の話は「プルリクエストとは:作り方・レビュー・マージの流れ」、プランと権限の話は「GitHubの権限と2段階認証:共同作業者・Organization・非公開リポジトリ」にあります。

Settings の Branches で、main に必須レビューをかける項目の位置
Settings の Branches で、main に必須レビューをかける項目の位置

Git FlowからGitHub Flowへ移す

develop をやめるときは、中身を main に入れてから枝を消します。枝を消すと、まだ合流していないコミットはその枝から見えなくなります。動かす前に、消す枝で作業中の人がいないことを確かめてください。

  1. 全員の作業中の枝を、先に develop へ入れるか、作り元を main に直します。
  2. develop を main へ合流します。
  3. main を送ります。
  4. GitHubで develop が既定の枝(最初に開く枝)なら、「Settings」の「Default branch」で main に変えます。管理者の権限が要ります。「Update」を押すと警告が出るので、「I understand, update the default branch.」を押します。枝が2本以上ないと変えられません。組織のルールセットがあるときは、組織の管理者が変更します。
  5. develop を送り先と手元で消します。
$ git switch main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.

$ git merge develop
Merge made by the 'ort' strategy.

$ git push origin main
To ../remote/website.git
   62c3102..25feb43  main -> main

$ git push origin --delete develop
To ../remote/website.git
 - [deleted]         develop

$ git branch -d develop
Deleted branch develop (was a062ed0).

$ git branch -a
* main
  remotes/origin/main
Settings の Default branch で既定の枝を切り替え、Update を押す手順
Settings の Default branch で既定の枝を切り替え、Update を押す手順

できないことと、その代わり

できないことその代わり
決めごとをGitの設定で強制する枝の保護で main だけでも止める。Freeの非公開で使えないならプランを見直すか約束で回す
1つのやり方でどの製品にも合わせる製品ごとに決めてよい。リポジトリごとに違っていても困らない
枝の決めごとで不具合を防ぐ決めごとは順番を整えるだけ。確かめる作業はプルリクエストと自動のテストで別に用意する
間違えて main に入れたものを、枝の決めごとで戻す「Gitで元に戻す:revert・reset・restoreの違いと使い分け」のrevertで打ち消す

よく詰まるところ

症状原因直し方
'flow' is not a git command拡張が入っていない入れなくていい。この記事の手順は普通の git で動く
プルリクエストをマージしたのに本番が変わらないGit Flowのリポジトリで develop に入っただけmain に入る次のリリースを待つか、外注先に出す時期を聞く
プルリクエストの送り先を main にしてしまった枝の決めごとと送り先が違うタイトルの横の「Edit title」(鉛筆)を押し、base の一覧から develop を選び、「Change base」を押す。一部のコミットやレビューの表示が変わることがある
develop に直したはずの修正が無い緊急修正を main にだけ入れたdevelop にも合流する
リリースのときに CONFLICT が出た緊急修正が develop に入らないまま、同じ行を develop で変えた「コンフリクトの直し方:起きる理由と、解消の手順」で直す。git merge --abort でいったんやめられる
cloneすると develop が開く既定の枝が develop になっているGit Flowの運用ならそのままでよい。やめるなら上の手順で変える

緊急修正を main にだけ入れて、develop を確かめると次のようになります。

$ git switch develop
Switched to branch 'develop'

$ grep -n お問い合わせ index.html
2:<p>お問い合わせ: 03-0000-1111</p>

古い番号のままです。この状態で develop が同じ行を変えていると、次のリリースで止まります。

$ git merge --no-ff release-1.2
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

AIに作業を頼むときは、どの枝から切ってどの枝に戻すかを最初に指定します。指定しないと、main から切る前提で進むことがあります。

次に読む

枝を切って合流する操作は「git branchとmergeの使い方:枝を分けて合流する、GitHub Flowまで」、見てもらう流れは「プルリクエストとは:作り方・レビュー・マージの流れ」にあります。誰に何を許すかは「GitHubの権限と2段階認証:共同作業者・Organization・非公開リポジトリ」、入れたものを取り消すときは「Gitで元に戻す:revert・reset・restoreの違いと使い分け」へ。

あわせて読む