CH 28 / 75第4部 ブランチとマージ

ブランチ戦略(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 と短い作業ブランチだけ、Git Flow は main・develop・feature・release・hotfix の5種類のブランチ、trunk-based は main にごく短いブランチをこまめに取り込む形であることを、3段に並べて比べた図
3つのブランチ戦略は、長く残るブランチの数と、作業ブランチの寿命が違う

GitHub Flow:main と短い作業ブランチだけ#

長く残るブランチは main の1本だけです。GitHub の公式ドキュメントでは、次の流れで説明されています。

  1. main から、内容が分かる名前の作業ブランチを作る
  2. 作業ブランチでコミットし、GitHub に送る
  3. プルリクエスト(取り込んでほしいという依頼。第7部の45で扱います)を作る
  4. レビューの指摘に、追加のコミットで応える
  5. 承認されたら main にマージする
  6. 作業ブランチを消す

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 FlowGit Flowtrunk-based
長く残るブランチmainmain・developmain
作業ブランチの寿命数日機能ができるまで(長くなりがち)数時間〜1〜2日
リリースマージしたらすぐまとめて、決まった時期にいつでも(常に公開できる状態)
向いているものWeb サイト・サービス、小〜中規模のチームバージョン番号を付けて出すアプリ・ライブラリ自動テストが整った、頻繁に更新するサービス

迷ったら、GitHub Flow から始めるのがおすすめです。ブランチは main と作業ブランチだけ、作業ブランチは小さく作って早めに取り込む、というだけで、個人でもチームでも十分に回ります。複数のバージョンを並行して保守する必要が出てきたら Git Flow の考え方を、取り込みの頻度をもっと上げたくなったら trunk-based の考え方を取り入れる、という順で十分です。

ブランチ名の付け方#

どの戦略でも、作業ブランチには何の作業かが分かる名前を付けます。feature/(機能の追加)や fix/(不具合の修正)のように、種類を / の前に付ける書き方がよく使われます。

text4 lines
cd ~/git-practice
git branch feature/rice-recipe
git branch fix/egg-count
git branch --list 'feature/*'
text1 lines
  feature/rice-recipe

git branch --list 'パターン' で、名前が合うブランチだけを一覧できます。/ で区切ると、種類ごとに絞り込みやすくなります。

第3部の19で見たとおり、ブランチの実体は .git/refs/heads/ の下のファイルなので、/ を含む名前はフォルダとして保存されます。

text1 lines
ls .git/refs/heads/feature
text1 lines
rice-recipe

このため、feature というフォルダがある状態で、feature という名前のブランチは作れません。

text1 lines
git branch feature
text1 lines
fatal: cannot lock ref 'refs/heads/feature': 'refs/heads/feature/rice-recipe' exists; cannot create 'refs/heads/feature'

feature と feature/〜 を同時に使うことはできない、と覚えておいてください。練習用のブランチは消しておきます。

text1 lines
git branch -d feature/rice-recipe fix/egg-count
text2 lines
Deleted 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部です。書きかけの変更をコミットせずにいったん脇へ置き、ほかのブランチへ移る方法を扱います。