ブランチ戦略(GitHub Flow / Git Flow / trunk-based)
このページで分かること
- ブランチ戦略が「ブランチの切り方と取り込み方の決めごと」だと分かる
- GitHub Flow・Git Flow・trunk-based の違いを、ブランチの数と寿命で説明できる
- チームや作るものに合わせて、戦略を選ぶ目安が分かる
feature/〜のような名前の付け方と、その注意点が分かる
このページの目次9 items
21〜27で、ブランチを作り、マージ・rebase・cherry-pick で取り込む道具がそろいました。第4部のしめくくりに、それらを「どう使うか」のチームの決めごと、ブランチ戦略を扱います。代表的な3つを比べ、どれを選べばよいかを考えます。
ブランチ戦略とは#
1人で使っているうちは、ブランチをいつ作り、いつ main に入れるかは自由です。ところが複数人になると、次のようなことを決めておかないと混乱します。
- どのブランチが「完成品」か(公開・リリースするのはどれか)
- 作業ブランチは、どこから作って、どこへ取り込むか
- 取り込むのはマージか rebase か、取り込む前に誰が確認するか
この決めごとのひな形が、ブランチ戦略(ブランチ運用のモデル、ワークフローとも呼ばれます)です。よく知られているのが GitHub Flow・Git Flow・trunk-based の3つです。違いはおもに「長く残るブランチが何本あるか」と「作業ブランチがどのくらいの期間で取り込まれるか」です。
GitHub Flow:main と短い作業ブランチだけ#
長く残るブランチは main の1本だけです。GitHub の公式ドキュメントでは、次の流れで説明されています。
- main から、内容が分かる名前の作業ブランチを作る
- 作業ブランチでコミットし、GitHub に送る
- プルリクエスト(取り込んでほしいという依頼。第7部の45で扱います)を作る
- レビューの指摘に、追加のコミットで応える
- 承認されたら main にマージする
- 作業ブランチを消す
main は「いつでも公開できる状態」に保ち、マージしたらすぐ公開する前提です。決まりが少なく覚えやすいので、Web サイトやサービスのように、こまめに更新して公開するものに向いています。
このガイドの第4部でやってきたこと、つまり「main から作業ブランチを作り、終わったら main に取り込んで消す」は、ほぼこの形です。
Git Flow:役割ごとに5種類のブランチ#
2010年に Vincent Driessen 氏が「A successful Git branching model」という記事で発表したモデルです。長く残るブランチが2本あり、そこに3種類の一時的なブランチが加わります。
| ブランチ | 寿命 | 役割 |
|---|---|---|
main(元の記事では master) | ずっと | リリースした版だけを置く。リリースごとにタグを付ける |
develop | ずっと | 次のリリースに向けて開発を集める |
feature/〜 | 機能ができるまで | develop から作り、develop へ取り込む |
release/〜 | リリースの準備期間 | develop から作り、仕上げてから main と develop の両方へ取り込む |
hotfix/〜 | 緊急の修正が終わるまで | main から作り、main と develop の両方へ取り込む |
「バージョン 2.0 を何月何日に出す」のように、まとまった単位でリリースするもの、複数のバージョンを並行して保守するものに向いています。一方で、ブランチの種類が多く、どこからどこへ取り込むかを間違えやすいのが難点です。
trunk-based:main にこまめに入れる#
trunk(幹)は main のことです。全員が main に、少なくとも1日に1回程度の頻度でこまめに取り込みます。 作業ブランチを作る場合も、数時間から1〜2日で取り込む短命なものに限ります。
ブランチが短命なので、24のコンフリクトが大きくなりにくく、「長く放置したブランチを取り込むのが大変」という問題がそもそも起きません。その代わり、作りかけの機能も main に入ることになるので、自動テストで壊れていないことを常に確かめ、未完成の機能は設定で隠しておく(フィーチャーフラグと呼ばれます)といった仕組みが前提になります。
どれを選ぶか#
| GitHub Flow | Git Flow | trunk-based | |
|---|---|---|---|
| 長く残るブランチ | main | main・develop | main |
| 作業ブランチの寿命 | 数日 | 機能ができるまで(長くなりがち) | 数時間〜1〜2日 |
| リリース | マージしたらすぐ | まとめて、決まった時期に | いつでも(常に公開できる状態) |
| 向いているもの | Web サイト・サービス、小〜中規模のチーム | バージョン番号を付けて出すアプリ・ライブラリ | 自動テストが整った、頻繁に更新するサービス |
迷ったら、GitHub Flow から始めるのがおすすめです。ブランチは main と作業ブランチだけ、作業ブランチは小さく作って早めに取り込む、というだけで、個人でもチームでも十分に回ります。複数のバージョンを並行して保守する必要が出てきたら Git Flow の考え方を、取り込みの頻度をもっと上げたくなったら trunk-based の考え方を取り入れる、という順で十分です。
ブランチ名の付け方#
どの戦略でも、作業ブランチには何の作業かが分かる名前を付けます。feature/(機能の追加)や fix/(不具合の修正)のように、種類を / の前に付ける書き方がよく使われます。
cd ~/git-practice
git branch feature/rice-recipe
git branch fix/egg-count
git branch --list 'feature/*' feature/rice-recipegit branch --list 'パターン' で、名前が合うブランチだけを一覧できます。/ で区切ると、種類ごとに絞り込みやすくなります。
第3部の19で見たとおり、ブランチの実体は .git/refs/heads/ の下のファイルなので、/ を含む名前はフォルダとして保存されます。
ls .git/refs/heads/featurerice-recipeこのため、feature というフォルダがある状態で、feature という名前のブランチは作れません。
git branch featurefatal: cannot lock ref 'refs/heads/feature': 'refs/heads/feature/rice-recipe' exists; cannot create 'refs/heads/feature'feature と feature/〜 を同時に使うことはできない、と覚えておいてください。練習用のブランチは消しておきます。
git branch -d feature/rice-recipe fix/egg-countDeleted branch feature/rice-recipe (was deb9a28).
Deleted branch fix/egg-count (was deb9a28).よくある疑問#
Q. 1人で使うだけでも、ブランチ戦略は必要ですか?
A. 厳密な決まりは要りませんが、「main はいつも動く状態にしておき、作業はブランチで行う」とだけ決めておくと便利です。途中で別の作業が割り込んでも、main に戻れば落ち着いて対応できます。
Q. develop ブランチを作るべきですか?
A. Git Flow を採用するなら必要です。そうでなければ、main とは別に長く残るブランチを増やすと、どちらが最新か分かりにくくなります。GitHub Flow や trunk-based では作りません。
まとめ#
- ブランチ戦略は、ブランチをどう切り、どこへどう取り込むかのチームの決めごと
- GitHub Flow は main と短い作業ブランチだけ。マージしたらすぐ公開する
- Git Flow は main・develop と feature・release・hotfix の5種類。まとめてリリースするソフトウェア向け
- trunk-based は main にこまめに取り込む。自動テストなどの仕組みが前提
- 迷ったら GitHub Flow から。ブランチ名は
feature/〜のように種類が分かる形で付ける
次のページ#
29. stash ── 作業を一時退避する ── ここから第5部です。書きかけの変更をコミットせずにいったん脇へ置き、ほかのブランチへ移る方法を扱います。