長らくGitFlowを使っていますが、GitHub Flowを使っている案件に携わってみて、疑問を感じたので、どっちが(もしくは別の方法)が良いかを改めて考えてみました。

GitFlowとGitHub Flowの違い

端的に言うと、developが有る(GitFlow)か、developが無い(GitHub Flow)かの違い。
リリース後は、masterdevelopが一致するので、2つは不要と、2つあると乖離する可能性があるというのが、GitFlowの欠点らしい。

GitFlowではブランチと環境が一致させられるので、STGがdevelopで、本番がmasterになる。
GitHub Flowでは、STGがmasterで、本番はmasterの特定の位置(タグ等で管理)になる。

featureブランチ

ブランチ名(例): feature/123_xxxxx

GitFlowはdevelop、GitHub Flowはmasterから切って、元のに向けてPRを作るので、対象が変わるだけで手順は変わらない。

hotfixブランチ

ブランチ名(例): hotfix/xxxxx

GitFlowはmasterから切って、developmasterに向けてPRを作る。
欠点:developマージを忘れるとmasterとの乖離が発生する。
解決策: STGで動作確認、本番リリースという流れを守れば、乖離する事はない。

GitHub Flowでは、featureブランチと同じ流れになる。
欠点:masterに動作確認できていないものが含まれているとリリースできない。
対応: 動作確認を急がせる or リバートする。 → 急いでいる時に手間が増えるのは痛い。

ECSやK8s(Kubernetes)、Capistrano等を使っている場合は、切り戻すのが早いのですが、
切り戻せないケースもあるので、hotfixが使えないのは痛い。

releaseブランチ

ブランチ名(例): release/123_xxxxx

masterマージ後のdevelopから切って、developmasterにマージする。

ブランチ名(例): release/123_xxxxx <- release/feature/123_yyyyy

私は、厳密にreleaseブランチの流れを使った事はないですが、
PRが大き過ぎる場合に、developの最新から切って、そこからfeatureブランチ切って、releaseブランチに向けてPRを何回かに分けて出して、最終的にreleaseブランチをdevelopに向けたPRを出してマージしています。develop向けのPRは動くものにした方が良い。
この流れはGitHub Flowでも使えます。

ちなみに、PRが大き過ぎても分割せず、featureブランチで行く事もあります。
この場合は、コミット単位が重要で、多過ぎない意味のある単位でコミットを積んでいれば、コミット毎にレビューする事が可能になります。
続けてレビューするか、別々にレビューするかの違いですが、チームによっては、大きいのを嫌がるので、使い分けています。

それぞれの課題

GitHub Flowの課題

GitHub Flowではmasterはリリースできる状態を保つ必要がある。ゆえにマージ&STGデプロイされたら、直ぐに動作確認しなければならない。

STGでは短時間で完了する必要がある為、詳細な動作確認(テスト)はマージ前に、ローカルやブランチ専用の環境(検証環境)で行う必要がある。→ ローカルでテストするのは微妙

検証環境が、本番やSTGと同様、連携先含め常に動く状態を保つ必要がある。→ これが結構難しい
STGで動作確認(テスト)しようとすると、リリースブロック(バグがあってもリリースできない状態)が必要になる。

GitFlowの課題

GitFlowではdevelopがリリースできる状態にならないと、masterマージ(=リリース)できない。
GitHub Flowと異なり、直ぐに動作確認(テスト)しなければならない訳ではないので、後回しが続くとリリースできない状態が続く。

ゆえに、予めリリース日を決めて(定期リリース)、そこに向けてテストする事が多い。
定期リリース以外にリリースする場合、動作確認(テスト)が完了しているかの確認と、マージブロックが必要になる。

リリースタイミング

GitHub Flowではhotfixが使えないので随時リリースしか選択肢がないが、
GitFlowでは定期リリース以外の選択肢も取れる。

GitHub Flowじゃないと、リリース頻度を上げられない?

No。GitFlowではdevelop、GitHub Flowではmasterが、リリース可能な状態になっていればいつでもリリースできる。但し、GitHub Flowではマージ前に検証環境でテストするのに対して、GitFlowではdevelopマージ後にテストするので(検証環境で事前にテストする事も可能)、リリース可能な状態の時間が短くなる。

GitHub Flowの方がリリース可能な状態が長いので、リリース頻度を上げやすいが、
GitFlowでも検証環境を使えばリリース可能な状態の時間は変わらない。

随時リリースは非効率!?

PRをマージしたら必ずリリースしなければならない訳ではない。
バグ対応や機能追加は早くユーザーに届けたいけど、リファクタやテスト追加、プログレッシブデリバリー(早期マージ。Feature Flagや環境変数(本番サーバーかどうか)でリリース制御)等の場合は、急いでリリースする必要がない。

未リリースのPRが溜まって行くが、皆が直ぐに動作確認したとしても、開発者の人数に比例して、リリースできない状態が長くなる。
直ぐに動作確認してくれない人も出てくるので、確認の為のコミュニケーションコストが増える。
環境にもよりますが、10人前後なら問題なさそうだが、20人ぐらいになると開発ストレスが増える。逆に数人だとリリースされない期間が長くなる。

リリース作業は自動化されている場合が多いとは言え、完了までに時間は掛かるし、経過観察も必要になるので、リリース回数が多いと効率が悪い。
ゆえに、リリース作業は避けたくなるので、気を利かせた特定の人にリリース作業が集中する。

定期リリースだと価値提供が遅れる

決まった日にリリースする方が効率的ではあるが、ユーザーへの価値提供は遅くなる。
とは言え、バグ対応を除けば、毎日届けたいものがあるかと言うと疑問な場合が多く、開発ストレス軽減も考慮すると週1〜2回で十分だと思う。

定期リリース以外に、特定の機能だけの臨時リリースを入れられれば、最短で価値提供でき、他のチームやメンバーに負担が掛からないのでベストだと思う。

夕方以降や休前日のリリースは避ける

リリース起因で、障害(インシデント)が発生した場合に、定時での対応が難しくなるので、定期リリースでは日時を気にする事が多い。
随時リリースだと気にしない事が多いと思われるが、気にした方が良い。自分たちの首を絞める。
※DB処理に時間や負荷が掛かったり、メンテナンスが必要なリリースは除く。

【解】GitFlow+定期リリース&hotfixを使用した臨時リリースの提案

GitHub Flowは少人数か、常にルールを守れる(開発ストレスを減らせる)場合は良いと思うが、hotfixが使えないのは痛過ぎる。
定期リリースは開発ストレスを減らせるが、ユーザーへの価値提供が遅れる。

価値提供は随時リリースでなくても、臨時リリースでも早くできる。
但し、masterdevelopとの乖離が長いと、コンフリクトや思わぬバグに見舞われる事もあるので、長期開発ではプログレッシブデリバリーを使った方が良い。

固定概念を捨てる

hotfixは緊急リリース用と思いがちだが、機能開発に使用しても問題ない。

ブランチ名(例): hotfix/123_xxxxx or <- hotfix/feature/123_yyyyy

臨時リリースしたい(定期リリース前にリリースしたい機能がある)場合に、
hotfixの流れで、masterからブランチを切って、developにPR・マージ&STGで動作確認した後、masterにPR・マージしてリリースする。

もし定期リリース直前になってしまったら、developだけにして、定期リリースの流れに乗せる。
もし定期リリース後になってしまったら、masterをマージして、開発を継続できる。

これで開発ストレスも増やさずに、価値提供のスピードも上げられる!!!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です