外注先から「うちはGit Flowです」「developに向けてプルリクエストを出してください」と言われて、何のことか分からなかった人向けの話です。Git FlowもGitHub Flowも、Gitの機能ではありません。枝(ブランチ)をどう分けて、いつ合流させるかの決めごとです。サンプル料理教室のホームページを例に、同じ変更を2つのやり方で実際に動かして比べます。読み終わると、自分の会社がどの決めごとで回せばいいかを選べて、外注先の話にも付いていけます。
この記事の内容
先に答えると
Git Flowは main develop に加えて機能・リリース準備・緊急修正の枝を使う、版番号を付けて出す製品向けの型です。GitHub Flowは main と短い作業の枝だけで回す型です。小さな会社のホームページや社内のスクリプトなら、GitHub Flowで足ります。
- どちらも決めごとで、Gitに設定する機能ではありません
- 一人で直しているなら
mainだけで十分です - 数人で触るならGitHub Flowにします
- 同じものを版ごとに分けて配り、古い版も面倒を見るならGit Flowを考えます
- Git Flowの提案者自身が、Webアプリのように更新を出し続けるものにはもっと単純な型を勧めています
2つを比べる
| GitHub Flow | Git Flow | |
|---|---|---|
| 残し続ける枝 | main の1本 | main と develop の2本 |
| 一時的な枝 | 作業の枝1種類 | 機能、リリース準備、緊急修正の3種類 |
| 向いているもの | 更新をすぐ出すサイトやツール | 版番号を付けて出す製品、複数の版を保守する製品 |
| リリースの仕方 | main に入ったものを出す | リリース準備の枝を作り、main に入れて版番号の印を付ける |
| 人数の目安 | 一人から始められる | 版の管理を決めて守れる人がいるチーム |
| 覚えること | 枝を切る、プルリクエスト、合流、枝を消す | 左の4つに加えて、枝ごとの作り元と合流先、印の付け方 |
人数の行は決まりではなく、実際に運用したうえでの目安です。プルリクエスト(Pull Request、PR)は、枝を本筋に入れる前に見てもらう依頼です。
GitLab Flowという名前を聞くこともあります。GitLabが紹介している型で、Git Flowより単純な代案という位置づけです。main に入れてから、必要に応じて production のような本番用の枝へ流します。本番の前に検証の環境を挟みたいときの考え方です。実際に運用していると、考え方だけならGitHubを使っていても借りられます。GitHubで使えるかどうかは、GitLabの説明には書かれていません。

Git Flowの枝
Git Flowは2010年に Vincent Driessen が自分のサイトで公開した型です。原典では本筋の枝の名前が master ですが、今のGitHubに合わせて main と読み替えます。
| 枝 | 役割 | 作り元 | 合流先 |
|---|---|---|---|
main | 本番に出ている版。合流のたびに版番号の印を付ける | 残し続ける | 残し続ける |
develop | 次の版を集める場所 | 残し続ける | 残し続ける |
| 機能の枝(feature) | 機能を1つ作る | develop | develop |
| リリース準備の枝(release) | 出す直前の版番号の更新や小さな直し。新しい機能は入れない | develop | main と develop |
| 緊急修正の枝(hotfix) | 本番の不具合をすぐ直す | main | main と 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-next | Towerが提供している後継 |
古い拡張の手順をそのまま入れないでください。普通の 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・非公開リポジトリ」にあります。

Git FlowからGitHub Flowへ移す
develop をやめるときは、中身を main に入れてから枝を消します。枝を消すと、まだ合流していないコミットはその枝から見えなくなります。動かす前に、消す枝で作業中の人がいないことを確かめてください。
- 全員の作業中の枝を、先に
developへ入れるか、作り元をmainに直します。 developをmainへ合流します。mainを送ります。- GitHubで
developが既定の枝(最初に開く枝)なら、「Settings」の「Default branch」でmainに変えます。管理者の権限が要ります。「Update」を押すと警告が出るので、「I understand, update the default branch.」を押します。枝が2本以上ないと変えられません。組織のルールセットがあるときは、組織の管理者が変更します。 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

できないことと、その代わり
| できないこと | その代わり |
|---|---|
| 決めごとを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の違いと使い分け」へ。