【GitFeatureFlow】GitFlowをやめて本番リリースが楽になった話

## 背景

サーバーサイド開発のプロジェクトでGitFlow(的な)運用を行っていたが、本番リリースの際に困ることがあったのでgitの運用フローを変えて解消したという話。
まず問題の内容から順番に書いているので、結論(新しい運用ルール)だけ知りたい人は[こちら](#新しい運用フロー)

git運用フローについては、GitFlow・GitHub Flow・GitLab Flowなどが有名だがどれとも少し違うように思ったのでまとめた。

<2018/06/10追記>
新フローにも名前が欲しいと思っていたが、同じやり方を「GitFeatureFlow」と呼んでいる記事を見つけた。個人的にもしっくり来たのでこれからはこの呼称を使っていこうと思う。
cf. [GitFlowは使わない！シンプルな「GitFeatureFlow」を紹介します](http://developers.gnavi.co.jp/entry/GitFeatureFlow/koyama)
<追記終わり>

### 導入プロジェクトの概要

採用するべき運用ルールはプロジェクトの条件にも依ると思うのでこのルールを導入したプロジェクトについて少し書く。

- 開発者(エンジニア)は10人未満
  - 比較的小規模なチームだが、1人2人よりは多い。
- 検証用サーバーには常にdevelopブランチの内容が反映される
  - developブランチに更新があればCIを通して自動でアップされる。
- 本番環境にはmasterブランチの内容を反映する
  - masterは常にリリースできる状態にしておく必要あり。
- featureブランチはローカル環境で開発する
  - 手元のMacで開発する人が多い。
- 検証用サーバーは一台
  - ブランチ毎にサーバーを立てることも検討したが、現状の運用では1台が良いという判断になっている。
- 本番リリースは数日~二週間に一度程度
  - 通常は一日に何度も本番リリースを行う感じではない。
  - リリース作業自体は、更新内容がmasterに入ってさえいればコマンド一発で完了するので作業コストは高くない。

## 元々の運用フロー

### ブランチモデル

GitFlowと書きつつ、正式なフローではなく、GitFlowからreleaseブランチを省いたような運用をしていた。

![](https://i.gyazo.com/3a7f3b9ab94ece16d4a0cd27091991c1.png)

- develop
  - 社内検証用ブランチ
- feature/xxx
  - ローカルでの機能開発用のブランチ
  - developから派生させる
- master
  - 本番動作用のブランチ

上記の図だと、2つのfeatureブランチが作られて、developへマージした際に検証用サーバーに反映される。
それぞれの動作検証がOKになった段階でdevelopをmasterへマージしてリリースという形。

### 他のfeatureの検証が終わってないとリリースできなくて困る

上記のフローで困るパターン。

![](https://i.gyazo.com/ebd976a445fe1c3b1468191fab0e9131.png)

先と同じ流れだが、先にfeature/2の方を検証がOKになった時点ですぐリリースしたいと思った時に困る。
検証がNGで修正が必要なfeature/1のcommitまで一緒にリリースされてしまうためだ。

すぐにfeature/1を修正・検証すればいいじゃないかと思うかもしれないが、プロジェクトの諸々の理由で簡単にできないことがある。
(例えば検証してみたら仕様変更が必要になったとか、担当者が次に作業できるのが3営業日後ですとか。修正がすぐにできたとしても、社内検証段階で最終チェックしてもらわないといけない偉い人がなかなか捕まらないとか。)

feature/2の方は検証まで済んでいるが、いつものフローではすぐにリリースはできない。feature/1の修正と検証が終わるまで待つか、もしくは一部のコミットだけcherry-pickするなどの対応を取らないといけなくなる。
これはブランチが2つ程度ならまだ良いが、開発人数が増えてそれぞれが別々に機能開発を進めているとリリースできるタイミングを調整するのがかなり面倒になる。

社内検証用のサーバーが1台しか無く、動作検証してから本番へリリース、という手順を踏む限りはGitHub FlowやGitLab flowでも同じ問題は発生すると思う。

## 新しい運用フロー

### ブランチモデル

![](https://i.gyazo.com/a2d3e77df066d1d05c982e97f36e8802.png)

このフローで利用されるブランチも3種類。

- develop
  - 社内検証用のブランチ。検証用サーバーに反映される。
  - 直接commit/pushされることはない。
  - 更新時はfeatureブランチをマージする。
- master
  - 本番動作用のブランチ。本番用サーバーに反映される。
  - 直接commit/pushされることはない。
  - 更新時はfeatureブランチをマージする。
- feature/xxx
  - ローカルでの機能開発用のブランチ。
  - **masterから派生させる。**
  - リリースしたい実装毎に作る。(同時に複数のfeatureブランチが存在しうる。)

GitFlowとの最大の違いは、常に**featureブランチをmasterブランチから切る**こと。
GitFlowでいうhotfixブランチに近い。こうすることでfeature毎にリリースが行えるようになる。

### メリット

- 機能毎にリリースができる
  - 他の人や機能とリリースタイミングを調整する必要がない。
- hotfixブランチを作る必要がない
  - featureは常にmasterから派生するため、hotfixブランチもいつものfeatureブランチと同じ扱いになる。
  - GitFlowだとリリース後の修正はイレギュラーなブランチ操作になるが、それと比べるとシンプル。

### デメリット

- feature毎にリリースまで面倒をみる必要がある。
  - developにマージしたからといってそのうち自動的に反映されるわけではないため、featureブランチの存在が忘れられると永遠にリリースされないということになってしまう。
  - とはいえタスク管理ツールのチケットとfeatureブランチを対応させておけばあまり困ることはないと思う。
  - Tipsとしては、featureブランチからdevelopへのPullRequestを出す時に、同時にmasterへのPullRequestを作っておくと忘れにくい。
- feature間でコンフリクトする可能性が高まる。
  - 長期間masterに反映されずに開発されるfeatureがあると、他のfeatureをdevelopへマージする際にコンフリクトする可能性が高くなる。
  - developマージ時にコンフリクトする場合は、原因になったfeatureブランチとの調整が必要になる。

## 所感

- 自分が参加してるプロジェクトではいろんな機能が並行して作られている。他の人の都合を考えずにリリースできるのでかなり運用が楽になった。
- その結果、いままでは全体の調整が面倒でリリースは二週間に一回程度だったのが、小さな機能追加・修正のリリースは二日に一回程度できるようになった。
- フロー図の作成には[Gitgraph.js](http://gitgraphjs.com)を利用。初めて使ってみたけどすごく使いやすかった！
- この運用してるプロジェクトや会社は他にもあるんじゃないかと思ったけど軽く検索しただけでは見つからなかったのでまとめた。

## 参考

Introducing GitFlow
https://datasift.github.io/gitflow/IntroducingGitFlow.html

GitHub Flow (Japanese translation)
https://gist.github.com/Gab-km/3705015

GitLab flowから学ぶワークフローの実践 | POSTD
https://postd.cc/gitlab-flow/

アプリ開発にはGitlab flowが合うと思います - Shoichi Matsuda's diary
http://shoma2da.hatenablog.com/entry/2015/11/04/233534

Gitgraph.js
http://gitgraphjs.com

GitFlowは使わない！シンプルな「GitFeatureFlow」を紹介します - ぐるなびをちょっと良くするエンジニアブログ
http://developers.gnavi.co.jp/entry/GitFeatureFlow/koyama