思い切ってハイブリットなブランチ戦略にした話

# はじめに
髙橋愛理です！  :frog:
AWSサーバーレス開発のチームリーダーやってます。

現在開発中のアプリの開発フェーズが進み、かつチームの人数も段々と増えてきたのですが、
ブランチ戦略に色々と限界を感じたため、思い切った戦略を考えてみました。

# 開発概要 
現在行っている開発概要は以下です。

- webアプリケーションの開発を行っている
- AWSを使用してサーバレス開発を行っている
- **dev、stg、prdの３環境**を用意
- CICDで、それぞれの環境名のブランチの変更をトリガーに、**自動デプロイするよう設定済み**
- ローカルでの動作確認が困難なため、**dev環境へデプロイしての開発や検証を行っている**　
- 総勢８名のチーム
- フロントエンド、バックエンド、インフラの３つのチームに分かれている
- それぞれ自分の担当領域外の部分を作業することもある
- **アジャイルでベンチャーチックなので柔軟にやりたい**
- ポテンシャル採用で未経験者を採用することも多い
- PLが管理業務以外に加え、設計や実装を行なうことがあり、作業負担が大きいためボトルネックになる時がある

# 試験運用までの開発状況
現在開発を行っているwebアプリケーションの開発が、今年5月に試験運用フェーズを迎えました。

それまでのチームの状況は以下です。
- チーム全員がアプリの基本機能の開発を行っていたので、作業の違いがそこまでなかった
- 実装に参加しているのは４人の少ないメンバーだったため、メンバー間の連携がとりやすかった
- リリース前だったのでバグがあってもそこまで問題にはならなかった
- **効率や開発速度を重視していた**

ブランチ戦略としては、開発を急いでいた前半は**github flow**を採用していました。
devブランチをマスターとし、こまめにマージを行うというシンプルな戦略をとることで、開発速度をかなり早めることが出来ました。

### 🟧 ブランチ戦略
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529351/163c1428-1989-da32-f310-64512621eb75.png)
### 🟩 ワークフロー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529351/e20d7a29-1693-db10-58de-d24e01b0c5ed.png)

ブランチ戦略とワークフロー採用の理由は以下です。

- 他の作業者の影響を受けずにどんどんマージを行える
- シンプルなので、チーム内で技術レベルに差があっても全員が理解しやすい
- リリース管理などのPLの作業を必要としないことで、ボトルネックを取り除いた
- そもそもリリースされていないので、リリース管理を厳密に行う必要が皆無だった

# 試験運用時の開発状況
一通り機能実装が終了したら、今度はdevブランチをstgに適用し、stgへのデプロイを行いました。
stgを使用しての試験運用フェーズでは、主に修正対応を行うことが多かったのですが、**gitlab flow**採用していました。
修正対応時もstgブランチへの直接の変更は行わず、通常featureブランチのフローと同じく、devブランチからfixブランチを作成しての対応を行っていました。

### 🟧 ブランチ戦略
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529351/4973fb21-d010-485b-dcca-1f3ebd01ee2d.png)

### 🟩 ワークフロー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529351/a1ae17cb-df44-58fc-9b24-6205bc7c18f6.png)

ブランチ戦略とワークフロー採用の理由は以下です。
- バグ修正毎にリリースまで行うので、対応が複雑化しない
- AWSリソースをデプロイしての検証が必要だったため、**dev環境でデプロイおよび検証をしっかり行っての対応が可能**
- devブランチへの作業をメインにするという以前までの流れを踏襲することで、経験の浅いメンバーがprdブランチに誤ってプッシュしたりなどの事故を防いだ

# 現在の開発状況と課題
試験運用フェーズ終了後、チームの状況は以下のように変化していきました。

- 未経験のメンバーが増えて、**技術力に差が出始めた**
- チーム全体の人数が増えたため、連携がとりにくくなってきた
- **効率よりも精度や確実性を高めていく必要が出てきた**

この状況だと、github flowもgitlab flowも、他で有名なgit flowもgit feature flowも、どれを選択しても、色々なことが担保できないなと、限界を感じました。

### ⬛ github flow パターン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529351/a9378a8c-4dcc-5c31-6d31-0edd5a0ff545.png)

### ⬛ gitlab flow パターン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529351/7f793dcb-0b8d-0789-4269-977e222bf4b7.png)

### ⬛ git flow パターン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529351/ae317391-6e07-808c-8ab4-541660145840.png)

### ⬛ git feature flow パターン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529351/3215e462-5535-5842-ca65-d39edfa3d6ef.png)

# 検討するにあたっての条件
以下を条件とし、新たなブランチ戦略およびワークフローを確立する必要がありました。
わがまま要望、てんこ盛りです…。。

- **しっかりとルール化されたワークフローを確立する**
  - 裁量の幅が大きく一人一人が多種類のタスクを持っているので、口頭ベースや特例での作業を極力避け、ワークフローから外れないで作業を行いたい
- **テストや動作確認は慎重に行いたい**
  - サーバレス開発なので、**AWS環境を直接使用してのテストや動作確認をしっかり行いたい**
  - 自動テストももちろん実施するが、**一部手動でのテストが必要な部分あり**
- 機能ごとに柔軟にリリースできるようにする
  - **別の機能を平行して開発するため、リリースは柔軟に行いたい**
  - リリースのタイミングをコントロールしたい
  - 機能実装時、バックエンドとフロントエンドの実装が双方依存するので、デプロイのタイミングを揃えたい
- 品質担保したい
  - **経験の浅いメンバーの参画も多いので、レビューはしっかり行いたい**  
- 開発効率は下げたくない
  - **PLの仕事が多いとボトルネックになってしまうので、負担自体は軽減したい**

# 検討結果
そこで、**git feature flowとgit flowのハイブリッド型**で、要件を全て網羅できるワークフローを作成してみました。
※以下、１つのreleaseブランチ（通知機能）に対して、３つのフェーズ（SAM実装、API実装、Stream実装）に分けて実装を行なう場合を例にしています

### 🟧 ブランチ戦略
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529351/9f0df101-2352-3b6c-b96e-995385c7a733.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529351/0db42782-e4b9-e7ec-d085-786ceb969949.png)

新しいブランチ戦略のポイントは以下です。
- **dev環境はgit feature flowの考えを採用**
  - **devは、あらゆる機能の動作確認として使用するという用途に限定**
  - 統合ブランチにせず、自由度を高くし、デプロイしての検証や動作確認がしやすくなった
- stg、prdにはgit flowの考えを採用
  - 複数リリースを含んだ場合でも、すべての変更を含んだ状態で、stgでの動作確認がしっかり行なえる
  - リリース日を設定し複数機能をリリースしたり、迅速にリリースしたり、柔軟なタイミングでリリースが行える
- 機能実装用としてリリースしても問題ない単位でreleaseブランチを作成
  - リリースしても問題ない独立した機能や修正単位でリリースブランチを作成し、**リリースをハンドリングしやすくなった**
  - 機能開発時、バックエンドとフロントエンドでタイミングを合わせてのリリースがやりやすくなった
- releaseブランチへのマージを前提とするfeatureブランチを作成
  - 一つの機能実装を分けて作業するfeatureブランチを作成する規約にし、機能実装のボリュームが多くなっても複数の工程に分けることができる
  - **工程をあえて増やすことで、内部レビューとPLレビューのフェーズを管理しやすくなった**
  - 経験の浅いメンバー実装の内部レビューを、ワークフローに含めたため、PLのレビュー負担が軽減した
 
### 🟩 ワークフロー
ブランチ戦略に合わせてしっかりとワークフローを確立することで、開発者が複雑なブランチ戦略を意識しなくてもいいようにし、工程の抜け漏れが無いようにしました。
これらを更に、**タスク管理ツール**を使用して、**何の機能実装がどの状態なのかを、自動で可視化できるようにした**ことで、リリース時にどの機能がデプロイされるかを、明確にしました。

#### １：featureブランチを実装
機能開発の統合用releaseブランチを作成し、そこから3つのfeatureブランチを切って開発を行います。
featureブランチの開発完了時は、チーム内レビューを行い、devへのマージと動作確認を行います。
PLレビューは、重要な機能や、難易度の高い実装を行なった際に実施します。
なお、実装時にリソースをデプロイして動作確認を行いたい場合は、引き続き、ローカルサーバでの確認や、CLIでのデプロイを行って確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529351/13c844da-4ed9-e635-98a1-dfab6f5c5c39.png)
#### ２：releaseブランチをstgへ反映
featureブランチの実装を全て終了し、releaseブランチにマージされたら、リリースの前日までにstgへ反映します。
**次回以降のリリースに回す場合は、作業を保留します。**
（※その時点で、何の機能を保留してあるかは、タスク管理ツールによって確認できるようにしました）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529351/6d801862-508d-2fd4-a102-7bac65119cbd.png)
#### ３：リリースしたいタイミングでリリース
リリースしたいタイミングでリリースします。
（※その時点で、stgに反映済みでリリース準備を終えているものは、タスク管理ツールによって確認できるようにしました）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529351/e564a746-119e-65fd-a32e-66550e2b8a2e.png)

:frog: 💭
<font color="DarkOliveGreen ">タスク管理ツールも、柔軟に対応できるものを選定したのが正解でした</font>

# 最後に
一見複雑なので、正直採用するか悩みました…。
が！ここをしっかり作っておかないと、かえって事故の原因になったり、後々ボトルネックが増える可能性があると思い、今回は思い切って採用した次第です。

シンプルだから、複雑だから、ではなく、今の状況的にベターな判断を選択していくことって結構大事だなと。
まぁこの戦略が今後どう生きてくるか、しばらく運用してみて、また機会があれば記事書きますので、見守ってやってください…🐸

ご参考になれば！