こんにちは! アスクルのたいち(Qiitaアカウント_taichi6930)です!
2025年9月、「ソロエルアリーナ」サイトのスマートフォン対応 を行いました!
このプロジェクトは、リリース時に大きな不具合なくリリースできたのですが、この要因として、ブランチ戦略を見直したことが大きいと考えています。
今回は、そのブランチ戦略の見直しと、実際にスマホ画面リリースに向けての開発でどのように活きたかを紹介します。
ブランチ運用の変遷
従来のブランチ運用
まず、約1年前のブランチ運用を見てみましょう。
| ブランチ名 | 詳細 |
|---|---|
| develop | 開発ブランチ(次回リリースに向けた統合ブランチ。各案件ブランチの変更をここに集約する) |
| epic/A, epic/B... | 案件ブランチ、プロジェクト単位で作成される |
| env/X, env/Y... | 環境ブランチ(デプロイ先の環境ごとに作成されるブランチ) |
ご覧のとおり、非常に複雑になっているのがわかりますでしょうか…!
図の中で注目してほしいポイントは次のとおりです。
- epic/A→develop取り込み、epic/B→develop取り込み: developへの保守変更を各案件ブランチに手動で取り込んでいる部分である。ブランチが多いほど取り込み回数が増える
- epic/C←epic/A、epic/C←epic/B: 案件ブランチ同士が直列に依存しており、リリース順序が固定されてしまう
- env/X←epic/A、env/X←epic/B: 環境ブランチと案件ブランチが紐づいており、環境を柔軟に利用できない
この図のブランチの関係性でも大変でしたが、実際にはさらに多くの(!!!)ブランチが存在していました。
困っていたことを次にまとめました。
ブランチが多すぎて管理が大変
ブランチが多すぎて、管理するのが非常に大変でした。
案件が複数並行で進行していることも原因ですが、それにしても多すぎる状況でした。
developブランチの取り込み時のコスト増加
たとえば、developに差分が入ると、各案件のブランチに取り込む必要がありました。
(図の中のepic/A→develop取り込み、epic/B→develop取り込み…の部分です)
ブランチが多いと、どれを取り込んだか忘れてしまったり、マージコンフリクトが発生することが多く、非常に大変でした。
また、リリース日まで資材を保持しておく必要があり、上記の問題が継続的に発生していました。
ブランチが直列に紐づいている
「この依存関係は本当に必要なのか?」という疑問が多くありました。
しかし、この依存関係によってリリース順序が固定されてしまうため、リリース順の変更に対応できませんでした。
ブランチと環境が紐づいている
こちらについても「この依存関係は必要なのか?」という疑問が多くありました。
柔軟に環境を利用・変更できず、開発スピードが低下していました。
また、動作確認用の環境をうまく活用できない開発者も多く、developにマージしてから初めて確認するといった状況になっていました。
現在のブランチ運用
「このままでは問題が深刻化する…」と判断し、ブランチ運用を見直すことにしました。
試行錯誤が続きましたが、最終的に私たちのチームのブランチ運用は次のようになりました。
| ブランチ名 | 詳細 |
|---|---|
| master | 開発ブランチ(本番リソースを管理する統合ブランチ。feature完了後すぐにマージされる) |
| feature/A, feature/B... | 作業ブランチ(案件単位よりも小さく) |
developブランチの取り込みをなくした
案件ブランチを作らないようにし、developブランチの取り込み自体をなくしました。
試行錯誤していた一時期、developブランチの取り込みは、GitHub Actionsで取り込み自体を自動化することで、手動での取り込みを減らしていたりしたのですが、結局はdevelopブランチの取り込み自体をなくすのが一番楽だと考えました。
これにより、案件ブランチ管理によって生じていたコンフリクト自体が発生しなくなりました。
画面の表示を各環境で出しわけしたい場合は、Feature Flagを使ってデプロイし、フラグでリリースするようにしました。
// 環境変数やCookie等、フラグ管理ツールで制御する val title = if (isVisibleNewTitle()) { "新しいタイトル" } else { "古いタイトル" }
より小さなブランチでデプロイサイクルを高速化
案件単位ではなく、機能単位でブランチを作成することで、より小さなサイクルで開発を回せるようになっています。
小さな機能単位でブランチを作成することで、作業ブランチでのコンフリクトも起きにくくなります。
また、リリース資材を溜め込むことなく、即座にデプロイリリースまで進められる準備ができます。
この流れにより、リリースまでの時間を大幅に短縮できます。
(もちろん、リリースのフローも変えないといけないのですぐに解決はできないですが、改善のための大きな一歩です。)
リリースロールバックが容易
個人的には、これがもっとも重要な要素だと考えています。
従来の方法でも問題ありませんが、この運用であれば1ブランチごとにデプロイとなるため、問題を発見した瞬間、即座にロールバックできます。
従来は他案件と混在して、「これは今日中にリリースしなければならない…」といった制約で障害が長引くことが多々ありましたが、これを防げるようになります。
環境の変更が不要に
環境ブランチが不要になることで、同じブランチで環境変数やCookieを制御するだけで、必要な状態を作成できます。
これにより、(データの不整合などの課題は残るものの)開発環境を多数用意する必要がなくなります。
開発環境を削減できれば、インフラコストも削減できるため、一石二鳥です。
スマホ画面リリースに向けた開発
ここまで、私たちのチームにおけるブランチ戦略の変遷について紹介しました。
次に、実際にスマホ画面リリースに向けた開発で、ブランチ戦略がどのように活用されたかを紹介します。
既存のPC画面コードとの共存により、バグ発生の可能性が減少
スマホ画面リリースでは、既存のPC画面とスマホ画面を共存させる必要がありました。
保守・エンハンスチームがPC画面、新規開発チームがスマホ画面を並行開発する体制で、画面のHTML・CSS・JavaScriptコードもPC・スマホで別々に管理されていました。
従来はブランチが分かれていたため、各チームがお互いのコードを把握しにくく、バグ発生のリスクが高い状況でした。
ブランチ戦略を見直したことで、両チームが同じブランチでコードを確認できるようになり、影響範囲を把握しやすくなりました。
さらに、画面のユニットテストを導入して自動検知を可能にしたことで、PC画面の改修取り込みの負担が大幅に減少しました。
開発・結合・UAT環境を柔軟に選択可能
スマホ画面用のソースが大本のブランチに統合されているため、開発・結合・UAT環境を柔軟に選択できるようになりました。
従来はブランチと環境が紐づいていたため、他案件で使われていない環境を探す必要がありました。
しかし、フラグで出し分けをすることで、他のプロジェクトで利用している環境でも動作確認を行えるようになりました。
不具合発生リスクを大規模リリース前に分散し、当日の負担を軽減
スマホ画面のコードが定期的に本番環境にデプロイされているため、既存システムへの不具合リスクを大規模リリース前に分散できました。
(もちろん、不具合を起こすことはしない前提ですが、大規模リリース時はどうしても気を張り詰めるため、当日の不具合リスクを減らせるなら減らしたいと考えています。)
リリースも、Feature Flagで事前に用意していたフラグを切り替えるだけで完了できるため、リリース当日の作業負担も大幅に軽減されました。
結果的に、既存システムへの影響なく大規模リリースを迎え、リリース後も大きな不具合なく完了できました!
おわりに
今回は、ブランチ戦略の見直しについて紹介しました。
ブランチ戦略を見直す際、「作業ブランチ同士で依存が生まれた場合はどうするの?」と疑問に思う方もいるかと思います。
私たちのチームの考え方としては、依存する部分(共通箇所)をなるべく早くmasterにマージしてしまうことを優先しています! Feature Flagで隠しながら共通箇所を先出しすることで、その後の作業ブランチを並列で進められるようになります。
また、本番環境でFeature FlagがFalseになっていれば、マージ自体は安心して行えます。リグレッションテストで元々の動きに問題がないことを確認するだけでいいので、影響を最小限に抑えながら小出しでマージできます。
このように、共通箇所の先出しマージ × Feature Flagによる安心したマージの組み合わせにより、ブランチ間の依存を気にせず、開発速度をさらに高められると考えています!
まだまだ社内では浸透していないので、今後も他チームに広めていきたいと考えています。
これからも生産性高く開発ができるように、改善を続けていきたいと思います!