🌳

小規模チーム開発のブランチ戦略を考える(GitHub Flowベース)

2024/05/05に公開

概要

筆者所属の小規模チームで採用したブランチ戦略について紹介します。
結論として、小規模チーム開発においてはGitHub Flowをベースに、必要な部分をアレンジしたブランチ戦略がマッチしやすいと考えます。

背景

筆者所属の小規模チームのスクラム開発において、ブランチ戦略が錯綜した時期がありました。
錯綜した結果として、管理している2つのブランチ間で齟齬が生じるようになり、ブランチ間の整合を合わせることに苦労しました。
そこで、シンプルで管理しやすく、仮にヒューマンエラーにより間違った運用をしてしまった場合も、リカバリしやすいブランチ戦略が求められました。

錯綜したブランチ戦略

開発当初は、git-flowをベースに少しアレンジしたブランチ戦略を採用していました。

ブランチ構成

ブランチ構成は次のとおりです。

  • main
    • 本番にデプロイするモジュールを作成するメインとなるブランチ
  • hotfix
    • 致命的なバグが発生した際に緊急で修正を加えるためのブランチ
    • mainから作成し、mainとdevelopにマージする
  • release
    • リリース対象の変更がマージされたブランチ
    • developから作成され、リリースのタイミングでmainにマージされる
  • develop
    • 開発環境にデプロイするモジュールを作成するブランチ
    • 開発環境でのテストに使用し、テストをパスしたタイミングでreleaseにマージされる
  • feature
    • 機能開発を行うブランチ
    • developから作成し、developへのマージ時点で削除する

この中で、永続的に管理をする必要があるのはmaindevelop2ブランチです。
また、本番にデプロイするのはmainですが、開発はdevelopを主軸に進めていきます。

起こったこと

開発が始まった当初は、次の流れで開発を進めていました。

  • 開発が終わったfeaturedevelopにマージ
  • developを開発環境にデプロイし、テスト
  • テストが完了したら、developからreleaseを作成し、リリースを待つ

しかし、開発を進める内に、スプリント内で開発がし切れず、リリースできない変更が出てきました。
実装、ソースレビューが終わり、developにマージしたものの、テストがし切れなかったり、テストで発生したバグの修正が間に合わなかったりなどの理由です。
developに乗った変更は何もしなければ最終的にmainにマージされるため、テスト未完了の変更はdevelopからrevertをすることで、リリースを回避、次のスプリントに回していました。

ただ、revertのし忘れにより未テストの変更がリリースされることを懸念し、developにマージしたfeatureのうち、テストをパスしたものだけを改めてreleaseにマージする運用に変更しました。
ここで、developmainの乖離が起きました。
テストをパスしたにも関わらず、releaseにマージし忘れることで、mainに反映されない変更が出てきたのです。

developmainの乖離に気付かず、開発はどんどん進んでいきました。
途中、hotfixが何度か挟まったこともあり、乖離に気付いた時には、developmainの間で競合が多く発生し、手作業での競合解決を余儀なくされました。

新たなブランチ戦略

元々のブランチ戦略でも、ルール通り運用ができれば、うまく回ったのだと思います。
ただ、スケジュールに追われる開発の中で、ブランチの管理にまで気を回すことができませんでした。
当初のブランチ戦略は自分たちのチームには手に余ると考え、機能開発が一段落したタイミングで、ブランチ戦略を変更することにしました。

変更後のブランチ戦略は、Github Flowを参考に、アレンジを加えたものにしました。

ブランチ構成

ブランチ構成は次のとおりです。

  • main
    • 本番にデプロイするモジュールを作成するメインとなるブランチ
  • hotfix
    • 致命的なバグが発生した際に緊急で修正を加えるためのブランチ
    • mainと進行中のreleaseに変更をマージする
  • release
    • リリース対象の変更がマージされたブランチ
    • mainから作成され、リリースのタイミングでmainにマージ、削除される
    • 開発環境でのテストに使用する
    • Github Flowの統合ブランチと似た用途だが、リリースごとに1つという特性がある
  • feature
    • 機能開発を行うブランチ
    • releaseから派生し、releaseマージ時点で削除する

主な変更点は、なんといってもdevelopを無くしたことです。
永続的に管理するブランチをmainのみにすることで、ブランチ間の整合を合わせる作業を最小限にしました。
releaseは、スプリント開始時に作成、リリース時点で削除することにより、スプリントごとにリセットされるようにしました。これにより、仮にmainreleaseで齟齬が発生したとしても、影響を最小限に抑えることができます。

おわりに

今のところ、このブランチ戦略はうまく回っています。
ただ、状況により適切なブランチ戦略は変化していくものだと思っているので、今後も柔軟に見直し、うまく開発を回していきたいと思います!

皆さんのブランチ戦略検討の一助になれば嬉しいです!

Discussion