この記事についてClaude(Anthropic)との共同編集により作成されました。
要約
- 業務では promote 型(環境ブランチ) を使っていたが、長命ブランチが増えてカオスになりがちだった。そもそも世の中にどんな手法があるのか知らなかったので、一次資料から整理した
- 現場で「git-flow」と呼ばれている
develop → release → mainの一方通行は、原文の git-flow ではなく promote 型である。原文は release / hotfix をmainとdevelopの両方へ戻す- trunk-based development(TBD)はリリースブランチ禁止ではない。禁止なのは長寿命の開発・統合ブランチのほうで、計画リリース時に trunk から短命のリリースブランチを切るのは正規のやり方
- 長命ブランチが増える原因は、戦略の選択ミスではなく空間の分岐をブランチで表していることが多い。顧客差・案件差はブランチではなく設定や flag に出す問題
- 下敷きにしたのは、
masterと出荷用ブランチだけで5世代を保守している PostgreSQL の構成。複数世代サポートでもdevelopは要らない、というのは実例で確認できた- ただし PostgreSQL はテストが薄いプロジェクトではない。無いのは自動テストではなく「CI が緑でないとマージできない」というゲートのほうで、検証はマージ地点になくてもよいが、どこかには要るという話に落ち着いた
業務では promote 型(develop → staging → production のように環境ごとにブランチを持つやり方)を使っていた。動くには動くのだが、気づくとブランチが増えていて、しかもどれも消せない。長命ブランチが積み上がっていくのがずっと課題だった。
ただ、じゃあ何に変えればいいのかというと、そもそも世の中にどんなブランチ管理手法があるのかを知らなかった。git-flow という名前は知っている、trunk-based という言葉も聞いたことがある、くらいの状態である。
なので、比較する前にまず並べるところから始めた。この記事はその整理と、整理して分かったこと・分からなかったことのメモである。
そもそも「1つ選ぶ問題」ではなかった
最初につまずいたのがここだった。git-flow と trunk-based と promote 型を横に並べて選ぶ、という前提で調べ始めたのだが、それだけでは足りない。
ブランチ管理には2つの軸がある。
| 軸 | 何を管理するか | 手法 |
|---|---|---|
| 時間(version) | 1つの製品がどう進化するか。v2.4 と v2.5、昨日の main と今日の main | git-flow / trunk-based / GitHub Flow / promote 型 |
| 空間(variant) | 似て非なる製品を何本同時に持つか。顧客 X / Y、車種 A / B | 設定・feature flag・別リポジトリ(増えるならプロダクトライン工学) |
git-flow も trunk-based も promote 型も、すべて時間軸の手法である。release/2.4 は時間の分岐だ。一方で project/A社 のようなブランチは空間の分岐で、モデルがまったく違う。
そして、私が「カオス」と呼んでいた状態も、時間の線と空間の線が同じリポジトリに混ざっていたのではないか、と読み直しているところである。後半でもう一度戻ってくる。
4つを並べる
先に結論の表を置く。
| git-flow | trunk-based | GitHub Flow | promote 型 | |
|---|---|---|---|---|
| 長寿命ブランチ | main と develop | 原則 main だけ | 原則 main だけ | 環境ブランチ(staging, production …) |
| ブランチを切る単位 | 版の安定化(終わったら消す) | 作業(数時間〜1日) | 作業(PR 単位) | 環境(ほぼ永久) |
| マージの向き | release / hotfix を両方へ戻す | 短い topic から main へ | 短い topic から main へ | 下流のみ |
| 本番の正本 | main のタグ | main(または短命リリース線) | main | production の HEAD |
| 向く本番世代数 | 2以上が並走 | 1 | 1 | 1 |
| デプロイ間隔 | 月〜四半期 | 日以下〜週 | 日〜週 | 週〜月(ゲート付き) |
「向く本番世代数」の行だけ補足がいる。複数世代を同時サポートしていても git-flow しかない、ということにはならない。trunk-based にリリースブランチを足す形でも回せる。後半で PostgreSQL を例に書く。
以下、それぞれ何が本体なのかを見ていく。
git-flow
Vincent Driessen が2010年に示したモデル1。寿命無限のブランチが2本ある。
main(原文ではmaster)— HEAD は常に本番投入可能。ここへのマージ=本番リリースdevelop— 次リリース向けの統合ブランチ
そのうえで、寿命が限られた補助ブランチを回す。
| 種類 | 分岐元 | マージ先 |
|---|---|---|
| feature | develop | develop |
| release | develop | develop と main |
| hotfix | main | main と develop |
見落としやすいのは戻しマージである。release を main にマージして終わりではなく、同じ release を develop にもマージする1。hotfix に至っては develop を経由せず main から切って、main と develop の両方に戻す。
理由は単純で、release や hotfix の上で入れたバグ修正と版番号を、次リリースの統合線から消さないためだ。ここを省略すると次の release で同じバグが復活する。
もう1つ重要なのが、著者自身が2020年に射程を狭めていることだ1。要約するとこうなる。
- 2010年に想定していたのは、明示的にバージョン付けされ、現場に複数世代が残るソフトウェアだった
- その後 Git の主流は Web アプリに寄った。Web は継続的に配信され、現場の複数世代サポートが不要なことが多い
- 継続的デリバリーをしているなら、git-flow を無理に当てず GitHub Flow のような単純なワークフローにせよ
- 一方、複数バージョンを同時サポートするなら git-flow は今でも適合しうる
「古いから捨てる」ではなく、CD 型か版管理型かで著者が自ら線を引いた、というのが正しい理解だと思う。
trunk-based development(TBD)
開発者が1本の trunk(main)に協調し、長寿命の開発ブランチを作らないモデル2。典型形は2段階ある。
- 小さいチーム — trunk へ直接 commit / push。事前に手元でビルドとテストを通す
- 規模が大きいチーム — 寿命の短い feature ブランチと PR。ブランチは「単一の開発ワークステーションの成果」で、数時間〜1日程度
DORA は TBD を継続的インテグレーションの必要条件と位置づけ、次を高パフォーマンスと関連づけている3。
- リポジトリのアクティブブランチは3本以下
- ブランチは少なくとも1日1回 trunk にマージする
- コードフリーズや統合フェーズを置かない
2021年の Accelerate State of DevOps Report では、信頼性目標を達成している elite 層は TBD を使う尤度が2.3倍だった4。もちろん TBD 単独の因果ではないが、方向としては強い。
GitHub Flow
git-flow と TBD の間にある軽いモデル56。
mainは常にデプロイ可能- 作業は説明的な名前のブランチで行う
- pull request でレビューし、マージ後にブランチを消す
TBD との差は程度問題である。ブランチが数時間で戻るなら TBD に近い。機能が終わるまで週単位で生きるなら、DORA の言う feature branch 開発の側に寄る3。PR を使っているから TBD、ではない。
promote 型(環境ブランチ)
ブランチが版ではなくデプロイ環境を表すモデル。名前付きの実装としては GitLab Flow の environment branches が代表78。
- 作業は
mainへマージする staging/pre-prod/productionなど、環境と同名の長寿命ブランチを持つ- 昇進は
main → staging → productionのマージだけで、上流へは戻さない - 各環境ブランチの HEAD が、その環境に載っているコードの正本になる
GitLab の文言は「commits only flow downstream」である7。全環境で同じ変更を順に踏ませたい、というのがこの向きを選ぶ理由になる。
hotfix だけ例外がある。GitLab は本番向け修正を feature ブランチで作り、先に production へ MR し、通ったら同じブランチを他環境にも出すと書いている7。下流専用を崩すためではなく、本番に入れた変更を他線で取りこぼさないための例外だ。
「git-flow をやっている」の多くは promote 型である
整理していて一番おもしろかったのがここだった。
現場でよく聞く「うちは git-flow です」の中身が、develop を release にマージして、それを main にマージして終わり、という一方通行のパイプラインになっていることがある。これは原文の git-flow ではない。版名を環境名に読み替えた promote 型である。
| よくある思い込み | 原文の git-flow |
|---|---|
develop を release にマージする | release は develop から分岐する。develop 全体を流し込む操作ではない |
release を main にマージして終わり | main へマージしたあと、同じ release を develop へもマージする |
| 本番修正も develop から release を通って main へ | hotfix は main から分岐し、main と develop へ戻す |
develop を直接 main にマージする日がある | 原文にその経路はない。本番へ行くのは release 完了か hotfix だけ |
図にするとこうなる。
[思い込み: 一方通行の昇進]
develop ──▶ release ──▶ main 上流へ戻る線はどこにもない
[原文の git-flow]
分岐: develop ──▶ release-* main ──▶ hotfix-*
マージ: release-* ──▶ main リリース release-* ──▶ develop 戻し hotfix-* ──▶ main 緊急リリース hotfix-* ──▶ develop 戻し名前が似ているだけで、グラフの向きが違う。GitLab 自身も、この「両方へ戻す」儀式を git-flow が重い理由の1つに挙げ、環境ブランチではコミットを下流へだけ流す、と対比している7。
紛らわしいことに、名前が似ていて中身が違うものが他にもある。Microsoft の Release Flow は promote 型ではない。本体は TBD で、スプリント末に releases/M130 を切り、hotfix は先に main へ入れてからリリース線へ cherry-pick する。リリース線は main へ戻さない910。
なので、自分たちのやり方に名前を付けるときは、ブランチの名前ではなくマージの向きで判定するのが早い。
- 下流へだけ流れる → promote 型
- release / hotfix を両方へ戻す → git-flow
- 短命ブランチが main に戻るだけ → GitHub Flow / TBD
trunk-based は「毎日20回デプロイしろ」とは言っていない
TBD を検討するときに引っかかりがちなのが、リリースブランチ禁止だと思ってしまうことだ。実際には禁止されていない311。
- 高頻度 CD — trunk から直接リリース。不具合は roll-forward(trunk で直して再デプロイ)。リリースブランチは不要
- 月次など計画リリース — リリース直前に trunk からリリースブランチを切る。開発は trunk に流し続ける。本番バグは原則 trunk で直してからリリース線へ cherry-pick する11
資料はこれを just-in-time なリリースブランチと呼んでいる11。「その場限りの使い捨て」という意味ではなく、必要になった時点で切るという意味である。切ったあと何年も保守されることもある(後述の PostgreSQL がまさにそれだ)。
重要なのは、リリースブランチが「凍結期間中に全員がそこにコミットする場所」ではないことだ。開発は止めない。
[TBD + リリース直前に切るリリースブランチ]
main ──t1──t2──t3──fix──t4──▶(開発は止めない) │ │ 切り出し cherry-pick ▼ ▼ release ●────────● v1.2.1 (main へは戻さない)そして、TBD が要求しているのは毎回本番に出すことではなく、main がいつでも出荷可能であることである。実際に出すかどうかはデプロイ判断で別問題、という整理になる23。ただしこの言い分けは解説側の整理であって、公式ポータルと DORA が明言しているのは「出荷可能であること」までなので、そこは区別しておいたほうがいい。
git-flow との最大の差は、常設の develop を持たないという一点に集約される。
自動テストが薄くてもTBDでいけるのか(ここからは仮説)
ここが私が一番知りたかったところで、そして資料からはクリーンな答えが出なかったところでもある。
資料側の立場ははっきりしている。TBD の成立条件として挙がるのは次で23、
- コミット前・マージ前に回る、数分で終わる自動テスト
- 未完成機能を本番に出さない feature flag、大きな置換のための branch by abstraction
- trunk が赤なら作業を止めて直す文化
- 小さなバッチに仕事を割る技能
そして「向かない場合」の筆頭が自動テストがほぼなく、main を緑に保つ手段がないケースである。つまり資料の言う TBD は、緑の trunk を前提にしている。
そのうえで私が引っかかっていたのは、trunk と出荷用ブランチという構成を昔からやっている実例があることだった。頭にあったのは PostgreSQL である。
PostgreSQLは実際に「trunk + 出荷用ブランチ」でやっている
PostgreSQL のリポジトリを見ると、構成は驚くほど単純だ15。
master— 開発の trunk。新機能はここにしか入らないREL_18_STABLE、REL_17_STABLE… — メジャーバージョンごとの出荷用ブランチ
develop に相当する常設の統合ブランチはない。そして重要なのは、新機能が入るのは master だけという点である。「新機能は常に master にコミットする。リリース済みのメジャーバージョンに機能を足さないのがプロジェクトのポリシーである」と明記されている16。出荷用ブランチに流れてくるのは、あとから back-patch されるバグ修正とセキュリティ修正だけになる1618。
修正の向きも TBD の教科書どおりだ。バグ修正はまず master で作り、そこから必要な安定版ブランチへ back-patch する。同じ修正を複数ブランチに入れるときはコミットメッセージも揃える、という運用になっている17。資料が言う「trunk で直してからリリース線へ cherry-pick」と同じ向きである11。
さらに面白いのは規模感で、PostgreSQL はメジャーバージョンを同時に5世代サポートし、各世代を5年間保守する18。マイナーリリースは四半期ごと(2月・5月・8月・11月の第2木曜)19。
これは資料の分類でいう「現場に複数世代が長く残る」ケースそのものである。そういう場合は git-flow が向く、と資料には書いてある1。ところが PostgreSQL は git-flow を採っていない。常設の develop を持たないまま、trunk + 出荷用ブランチで5世代を回している。
ここで、前に書いた DORA の「アクティブブランチは3本以下」3 が気になる。PostgreSQL は master に加えて、サポート中の世代ごとに1本ずつ生きたブランチを持っているので、字義どおりに数えれば引っかかる。
ただ、DORA も TBD も禁じているのは長寿命の開発ブランチのほうで、リリース線は両者とも正規のオプションとして扱っている311。出荷用ブランチには新機能が入らないので、そこで開発が分岐することはない。「アクティブ」を開発が並行している線の数と読めば、PostgreSQL は master 1本である——というのが私の読みで、ここは資料に明記されているわけではない。
つまり「複数世代をサポートしているから git-flow しかない」は成り立たない。ここは整理して一番はっきり収穫があった部分だった。
ただしPostgreSQLは「テストが薄い」プロジェクトではない
問題はここからで、PostgreSQL を根拠に「自動テストが無くてもいける」とは言えない。調べたら、むしろ逆だった。
- PostgreSQL には回帰テスト(SQL レベルの網羅的なテスト)と TAP テストが本体に入っている20
- committer には、コミット前に
make check-worldを回すことがチェックリストとして課されている17 - commitfest に登録されたパッチは cfbot が自動でビルドしてテストする。複数 OS 上で、まだツリーに入る前に回る21
- コミットが入ったあとは buildfarm が拾う。世界中のボランティアのマシンが、保守中の全ブランチを定期的にビルド・テストして結果を報告する仕組みで、多様なプラットフォームを網羅している22
だから正確に言うとこうなる。PostgreSQL に無いのは自動テストではなく、「CI が緑にならないとマージできない」という形のゲートである。committer は手元で check-world を通してから直接 push し、壊れは cfbot と buildfarm が前後から拾う。
仮説をこう言い直す
というわけで、当初の「リリースブランチで検証すれば自動テストが無くてもいける」は言いすぎだった。PostgreSQL から実際に読み取れるのはこうだ。
検証のゲートはマージ地点になくてもよい。ただし、どこかには必要である。
PostgreSQL はゲートを次の4か所に分散させている。
| いつ | 何が守っているか |
|---|---|
| コミット前 | committer が手元で make check-world17 |
| ツリーに入る前 | cfbot が複数 OS で自動ビルド・テスト21 |
| コミット直後 | buildfarm が全保守ブランチを継続ビルド22 |
| リリース前 | フリーズ後の長いベータ期間 |
最後の行が、私が「リリースブランチで検証」と呼んでいたものに一番近い。PostgreSQL 19 のサイクルでは、機能追加が2026年4月8日で止まり25、ベータ1が6月4日に出て、GA は9〜10月の予定である23。機能を止めてから出荷まで半年近く安定化に充てている計算になる。
そして、これは私の現場にそのまま持ち込める話ではない。ここで気づいたコストが2つある。
- フリーズ期間が長い。 機能開発のサイクルは7月の commitfest で始まり、翌年3月の commitfest が終わるとフリーズに入る24。裏を返すと、4月のフリーズから7月までは trunk に新機能が入らない期間になる。DORA が「コードフリーズを置くな」と言っているのは、まさにこれのことである3。年1回のメジャーリリースだから成立している
- レビューの厚みが違う。 commitfest は、パッチをレビュー担当と committer の手に順に通す仕組みで、月単位のレビュー期間が年5回組まれている24。新機能はすべて、コミット前に contributor と committer のレビューを通ることになっている19。自動テストが薄いチームは、この人手のゲートも持っていないことが多い
なので、仮説はこう修正する。
- trunk + 出荷用ブランチという形は正しい。複数世代サポートでも
developは要らない - ただし、マージゲートを外すなら代わりのゲートを明示的に置く必要がある。PostgreSQL でいう check-world / cfbot / buildfarm / ベータのどれに当たるものを自分たちは持つのか、を先に決める
- 手動検証だけで代替するなら、フリーズ期間という形でリードタイムを払うことになる。そこが払えるかはリリース頻度次第
弱点として最初に挙げていた点も、そのまま残る。
- 検証が手動なら、trunk が壊れていること自体はリリース直前まで見つからない(PostgreSQL は buildfarm でここを埋めている)
- back-patch の向きを間違える(出荷用ブランチで直して trunk に戻さない)と、次のリリースで回帰する。これは git-flow の戻しマージ忘れとまったく同じ失敗
- 「trunk が赤なら止める」文化がないと、結局リリース線が安定化フェーズになって develop が復活する
その手前に、成果物昇進という選択肢がある
もう1つ、整理して初めて意識したのが、promote という言葉が2つの別の操作を指していることだった。
| ブランチ昇進 | 成果物昇進 | |
|---|---|---|
| 何を動かすか | 環境ブランチ同士をマージする | 同じコミット・同じビルド成果物を次の環境に出す |
| Git 上の長寿命ブランチ | 環境の数だけ必要 | 不要 |
| 環境ごとの SHA | ずれてよい | 同一 |
| 相性 | promote 型(GitLab Flow が言う promote はこちら7) | TBD / GitHub Flow |
環境ゲートが欲しいだけなら、まず成果物昇進で足りるか見る、というのが素直な順序だと思う。「staging で確認してから本番」を実現するのに、必ずしも Git のブランチを増やす必要はない。ブランチ昇進を選ぶ理由は、「その環境に今何が載っているかを Git の HEAD で表したい」という要求があるときに限られる7。
長命ブランチが増えて困っている、という私の元の課題に対しては、環境ゲートが目的なら、ここだけで潰せるということになる。
長命ブランチが増える本当の原因
戦略の話に戻る。promote 型を使っていて長命ブランチが増えるのは、環境ブランチそのものが原因のこともあるが、それだけではないことが多い。
環境ブランチは環境の数だけしか増えない。それでもブランチがカオスになるなら、環境でも版でもない第3の長期線が混ざっている。顧客ごと、案件ごと、機種ごとのブランチだ。
これが冒頭の「空間の分岐」で、名前を付けるなら clone-and-own である12。既存のコードをブランチやリポジトリごとコピーして、個別に改変していくやり方だ。導入コストは低いが、本数が増えると次が起きる。
- バグ修正を何本にも手で移植する
- どの製品にどの変更が入ったか追跡できない
- マージが巨大化する
- テストが製品ごとに重複したり欠落したりする
重要なのは、この問題は時間軸のブランチ戦略をどれに変えても解決しないということだ。git-flow でも TBD でも promote 型でも、空間の分岐をブランチで表している限り同じことになる。
分類の観点としては、長命ブランチを1本ずつ次のどれかに振ってみるのが分かりやすかった。
| 型 | 中身 | ブランチである必要 |
|---|---|---|
| 時間 | 同じ製品の別世代。差分は版番号と安定化だけ | リリースブランチかタグで足りる |
| 空間・設定 | 接続先、ロゴ、文言、権限。コード差はほぼない | 不要。設定ファイルやテナント設定へ |
| 空間・機能 | その顧客だけが使う機能。本体に入れても他を壊さない | 不要。feature flag やモジュールへ13 |
| 空間・分岐 | 本体を深く改変。他に出すと契約や品質が壊れる | ブランチか、いっそ別リポジトリ |
未完成機能を隠すための一時的な flag と、顧客差を表すための長期の flag(entitlement)は別物で、後者は消す前提ではない、というのは言われてみると当たり前だが意識していなかった13。
カオスからきれいなTBDへ、は簡単ではない
ここも整理して分かったことだ。カオスな状態から一気に trunk-based へ移すのは、順番を間違えると悪化する。
いちばんまずいのが、develop を消して長命ブランチはそのまま残す、というやり方である。統合線が消えるだけで、残った長命ブランチが事実上の長期開発線になる。DORA の「アクティブブランチ3本以下・日次マージ」も、TBD の「長寿命開発ブランチを作らない」も満たさないので、名前だけ TBD になった状態が残る23。
やってはいけない移行として挙がっていたものを並べておく14。
| やり方 | 何が起きるか |
|---|---|
develop を消して長命ブランチはそのまま | 統合線が消え、長命ブランチが事実上の開発線になる |
全部を flag なしで main にマージ | 他の本番にコードが混ざる。契約・回帰のリスク |
| 名前のまま短い PR に分割しただけ | 可変性の正本がブランチのままで、細切れになるだけ |
| 本体は TBD、派生は従来どおり無期限 | 日次マージの規律が本体にしか効かず、移植コストは残る |
| 移行期限だけ切って差分を見ない | 大きい線ほど最後まで残り、二重運用が定着する |
そして、移行しないという判断もある。空間・分岐型の長命ブランチが少数あって、それぞれ独立した本番を持ち、年単位で個別にパッチしている、というような場合、共通化の投資が回収できないことがある。このとき失敗なのは移行しないことではなく、長命ブランチを残したまま「うちは TBD にした」と宣言することである。中途半端な中間状態は、git-flow の儀式と TBD の欠陥を両方抱えることになる14。
順序としては、こうなる。
- 長命ブランチを1本ずつ、時間・設定・機能・分岐に分類する
- 新規の長命ブランチを止める
- 設定を抜く(差分が設定だけの線はタグ1本に落とせる)
- 機能を flag やモジュールに移す
- 複数線にコピーされた汎用の修正を本体に戻す
- 深い分岐は別リポジトリにするか、期限付きで残す
- 残った時間軸の線だけを TBD 化する
移行できたと言えるのは、戦略の名前を変えたときではなく、新規の長命ブランチがゼロになり、手移植の本数が落ち、trunk が固有コードなしでビルドできるようになったときである。
個人開発では、ほぼ悩まなくてよかった
ここまで書いておいてなんだが、個人開発ではこの問題はほとんど発生しない。
このブログや個人アプリでは、main からブランチを切って、終わったらマージするだけでやっている。ブランチは長くても1日で消える。かなり楽だ。
分類すると、これは定義上は GitHub Flow である5。ただしブランチ寿命が数時間〜1日に収まっているので、実質的には TBD に近い。というより、1人なので統合の衝突が起きないというだけの話でもある。
ここから「だからチームでも main 一本でいける」とは言えない。個人開発で楽なのは、レビュー待ちがなく、他人の未完成コードが trunk に載らず、赤くなっても自分が5分で直せるからだ。TBD の成立条件を、規律ではなく人数1人という構造で満たしてしまっている。
チーム開発でmain一本にできるか
現時点では半信半疑である。ただ、目指す形は PostgreSQL 型に決めた。main に直接入れて、出荷用ブランチはリリースのたびに切る。修正は main で作ってから出荷用ブランチへ back-patch する。
そのうえで、試すときの判定基準を先に決めておく。TBD の成立条件23 と、PostgreSQL がゲートを置いている場所172122 を突き合わせると、聞くべきことはこうなる。
- 手元で回せる検証は何か。PostgreSQL の
make check-worldに当たるもの。ここが空なら、あとの全部が成立しない - 壊れを事後に見つける仕組みは何か。buildfarm に当たるもの。夜間ビルド1本でもいい。無いなら「trunk が赤い」ことに誰も気づけない
- ベータに当たる期間を取れるか。出荷用ブランチを切ってから出すまでに検証期間を置けるか。置けないなら、手動検証で自動テストを代替する案そのものが崩れる
- main が赤くなったとき、作業を止めて直す(か revert する)合意が取れるか
- 未完成機能を flag で隠せるか。隠す手段がないと、結局「完成するまでマージしない」=長命ブランチになる
- 仕事を小さいバッチに割れるか。これは技能の問題で、一番時間がかかりそうなところ
正直、最後の2つが怪しいと思っている。特に「小さいバッチに割る」は、ブランチ戦略の話に見えて設計とタスク分割の話なので、Git の運用ルールを変えただけでは身につかない。
環境ゲートについては、別の逃げ道もある。成果物昇進で代替できるなら、環境ブランチを残さずにゲートだけ残せる。ブランチ昇進を続けるなら、それは TBD ではなく promote 型との併用になる、と自覚したうえでやることになる。
やってみたら別の壁が出てくると思うので、そこはまた記事にする。
まとめ
整理して分かったことを並べておく。
- git-flow / trunk-based / GitHub Flow / promote 型は、すべて時間軸の手法。顧客差・案件差は空間軸の問題で、ブランチ戦略を変えても解決しない
- 現場の「git-flow」の多くは戻しマージのない promote 型。判定はブランチ名ではなくマージの向きで行う
- TBD はリリースブランチ禁止ではないし、毎日20回デプロイしろとも言っていない。要求は「main がいつでも出荷可能」
- PostgreSQL は
masterと出荷用ブランチだけで5世代を5年ずつ保守している。複数世代サポートでも常設のdevelopは要らない - 環境ゲートが欲しいだけなら、ブランチ昇進より成果物昇進を先に検討する
- カオスからの移行は、
developを消すところから始めると悪化する。空間の分岐を畳んでから時間の線を畳む - 個人開発は GitHub Flow 相当でほぼ悩まなくていい。ただしそれは規律ではなく人数1人で成立している
そして当初の仮説だった「自動テストが薄くても出荷用ブランチの手動検証で回るのでは」は、言いすぎだったと自分で結論した。PostgreSQL が示しているのは「テストが要らない」ではなく、ゲートはマージ地点でなくてもよいということである。マージゲートを外すなら、手元の検証・事後の検知・出荷前の検証期間のどれを代わりに置くのかを先に決める。ここを空欄のまま形だけ真似すると、ただ壊れた main を共有することになる。
チーム開発で試して、結果を書く。
参考文献
- Vincent Driessen, A successful Git branching model(2010-01-05。2020-03-05 に継続的デリバリー向けの射程修正を追記) https://nvie.com/posts/a-successful-git-branching-model/
- Paul Hammant ほか, Trunk-Based Development(ポータル) https://trunkbaseddevelopment.com/
- DORA, Capabilities: Trunk-based development https://dora.dev/capabilities/trunk-based-development/
- DORA / Google Cloud, 2021 Accelerate State of DevOps Report https://dora.dev/research/2021/dora-report/2021-dora-accelerate-state-of-devops-report.pdf
- GitHub Docs, GitHub flow https://docs.github.com/en/get-started/using-github/github-flow
- Scott Chacon, GitHub Flow(2011。初期の6規則) https://scottchacon.com/2011/08/31/github-flow/
- GitLab Docs, Introduction to GitLab Flow(環境ブランチは commits only flow downstream。hotfix は production へ先に出す) https://docs.gitlab.com/ee/topics/gitlab_flow.html
- GitLab, What is GitLab Flow? https://about.gitlab.com/topics/version-control/what-is-gitlab-flow/
- Edward Thomson, Release Flow: How We Do Branching on the VSTS Team, Azure DevOps Blog (2018-04-19) https://devblogs.microsoft.com/devops/release-flow-how-we-do-branching-on-the-vsts-team/
- Microsoft Learn, How Microsoft develops with DevOps https://learn.microsoft.com/en-us/devops/develop/how-microsoft-develops-devops
- Trunk-Based Development, Branch for release(just-in-time なリリースブランチ、trunk で直して cherry-pick) https://trunkbaseddevelopment.com/branch-for-release/
- Mahmood, Cloned Product Variants: From Ad-hoc to Well-managed Software Reuse(博士論文。clone-and-own の整理) http://hdl.handle.net/1807/68443
- LaunchDarkly, Using entitlements to manage customer experience(顧客ごとの release ブランチを flag に置き換える) https://docs.launchdarkly.com/guides/flags/entitlements/
- DeployHQ, Trunk-based development vs Gitflow(段階移行と中途半端な中間状態への警告。ベンダーブログ) https://www.deployhq.com/blog/trunk-based-development-vs-gitflow
- PostgreSQL Git リポジトリのブランチ一覧(
masterとREL_*_STABLE) https://git.postgresql.org/gitweb/?p=postgresql.git;a=heads - PostgreSQL Wiki, So, you want to be a developer?(新機能は master のみ。安定版ブランチにはバグ修正とセキュリティ修正だけ) https://wiki.postgresql.org/wiki/So,_you_want_to_be_a_developer
- PostgreSQL Wiki, Committing checklist(コミット前に
make check-world、back-patch は master から) https://wiki.postgresql.org/wiki/Committing_checklist - PostgreSQL, Versioning Policy(メジャー5世代を同時サポート、各5年) https://www.postgresql.org/support/versioning/
- PostgreSQL, Roadmap(マイナーリリースは2月・5月・8月・11月の第2木曜) https://www.postgresql.org/developer/roadmap/
- PostgreSQL Documentation, Regression Tests(回帰テスト、TAP テスト) https://www.postgresql.org/docs/current/regress.html
- PostgreSQL Wiki, Cfbot(commitfest 登録パッチを取り込み前に複数 OS で自動ビルド・テスト) https://wiki.postgresql.org/wiki/Cfbot
- PostgreSQL Wiki, PostgreSQL Buildfarm Howto(保守中の全ブランチを分散ビルド。コミット後に検出する仕組み) https://wiki.postgresql.org/wiki/PostgreSQL_Buildfarm_Howto
- PostgreSQL, PostgreSQL 19 Beta 1 Released!(2026-06-04。GA は2026年9〜10月の予定) https://www.postgresql.org/about/news/postgresql-19-beta-1-released-3313/
- PostgreSQL Commitfest, What is the Commitfest app?(年5回。7月開始で9か月の機能開発サイクル、最後は3月で、終わるとフィーチャーフリーズ。時期は年によるがおおむね4月上旬) https://commitfest.postgresql.org/help/
- pgsql-hackers, feature freeze for v19 begins April 8th at 12:00 UTC(2026年サイクルのフリーズ告知) https://www.postgresql.org/message-id/ab1YPhD9XNwQH7Kn@nathan