バックオフィスシステム開発におけるGitflowの使い方について
概要
グローバル開発グループの崔です。現在はGlobal KINTO Appチームのプロジェクトマネージャーを担当していますが、以前はグローバル開発Gで開発しているバックオフィスシステムのプロジェクトマネージャーを担当していました。
今回は、そのバックオフィスシステム開発チームにてソースコードを管理する際に採用した、Gitのブランチ管理方法(Gitflow)についてお話します。他のプロダクトにも流用できると思いますので、ぜひ参考にしてください。
Gitflow
注意:今回は、あくまで私の開発チームで採用したGitflowについて説明します。以下の説明ではブランチ名を「master」と書いていますが、GitHubを利用する場合、masterは古い呼び名になるため、現在ではデフォルトブランチは「main」になります。役割は全く同じです。
全体図は以下の通りです:
各ブランチの役割
master:
リリース済みのソースコードを管理し、本番環境に動いているアプリケーションと同じソースバージョンを持つブランチ。リリース毎にタグが付けられます。
develop:
開発済のソースコードをまとめるブランチ。本番環境にまだリリースされていない機能を含み、常に最新機能を持ちます。一般的には回帰テスト(regression test)はこのブランチでデプロイして実施されます。
feature:
新機能、修正機能の開発用ブランチ。開発する機能や、タスクなど単位でdevelopから分岐し、結合テストが完了したら、developにマージします。一般的には1つのユーザーストーリーにつき1つfeatureブランチが作れらますが、開発チーム内である程度自由に決めることができます。
hotfix:
リリース後のバグフィックス用ブランチ。masterから分岐し、バグを修正しテストを通ったら、このブランチで本番環境へデプロイします。本番作業が完了したら、該当ブランチをmaster, develop共にマージします。必要に応じて、一部のrelease, featureブランチにもマージします。
release:
プロダクトリリース用のブランチ。
リリース予定の機能が反映された状態でdevelopブランチから分岐します。
このブランチを使って本番環境へデプロイします。本番作業が完了したら、masterとdevelopブランチにマージして、該当ブランチを削除します。
support:
旧バージョンをサポートし続けなければいけないプロジェクトでは support ブランチが必要です。support ブランチでは、旧バージョンの保守とリリースを行います。サポートが必要なバージョンの master ブランチのコミットから派生させ、サポートを終了するまで独立してバグフィックスやリリースを行います。
bugfix:
上記5つ標準のブランチ種別以外、bugfixというブランチ種別も定義します。
詳細は後述しますが、リリースの前にバグが見つかった場合、releaseブランチからbugfixブランチを分岐して修正対応を行います。
開発の流れ
① 初期化作業
masterからdevelopを作成します。
注意: masterとdevelopブランチはGitflowのメインブランチとして常に存在するものになり、一度作成されたら、削除できません。(GitHubで設定する)
② 新機能、修正機能の開発
1.developブランチからfeatureブランチを作成し、新機能、修正機能の開発作業を開始します。
2.featureブランチの命名規則:feature/xxxx
その「xxxx」は開発チームが命名ルールを決めて良いです。
例:feature/GKLP-001、feature/refactoring、feature/sprint15
また、結合テストを行う前にpull requestを作ってソースレビューを行うため、主とするfeatureブランチからさらに作業用ブランチを作るのがお勧めです。具体的なパターンは後述します。
3.ソースコード修正のコミットは作業ブランチにて行い、終わったらPR提出し、他の人にレビューしてもらいます。
4.ソースレビューが完了したら、主とする機能ブランチにマージし、結合テストを行います。
5.結合テストが完了したら、developブランチにマージするPRを提出し、マージします。
注意:リリース計画により開発完了してもdevelopにマージしてはいけない時がありますので、 マージするタイミングを常に確認してください。
6.developにマージした後にfeatureブランチを削除します。
パターンNo.1: 機能ブランチと作業ブランチ
このパターンでは、該当機能ブランチから切ったすべての作業ブランチがマージ済みになってから、結合テストが行われます。
1つの機能の開発規模が大きく、複数スプリントを跨ぐことが見込まれる場合、このパターンを採用するのが適切です。
パターンNo.2: スプリントごとのブランチと作業ブランチ
このパターンでは、すべての作業ブランチがマージ済になってから結合テストを行うことに限らず、スプリント内の1機能に必要な開発分がマージ済みになったら、その機能に対して結合テストを行うのもいいです。
開発する機能が規模が小さく、1スプリント内で完了と見込まれる場合、このパターンを採用するのが適切です。
推奨しないパターン(No.3):機能と作業ブランチを同一にする
このパターンでは、PR提出と結合テストのタイミングがはっきりせず、developにマージする頻度も高くなるので、QAとリリース計画を作る際にとても面倒になると想定されます。そのような無計画なやり方は推奨しません。
その代わりに、システム開発、運用の際にちゃんとリリース計画して、それに合わせてfeatureブランチの切り方を決めるのがお勧めです!
③ リリース&デプロイ
- developブランチからreleaseブランチを作成する。
- releaseブランチにタグを付ける。(命名規則は下記のTag命名規則を参照)
- 本番環境へのデプロイが終了したら、releaseブランチをmasterブランチにマージする。
- マージ完了後にreleaseブランチを削除する。
リリース計画
本番環境にリリースする予定がある開発については、早めにリリース計画を作りましょう。
featureブランチの運用ルール、featureの機能ブランチをdevelopにマージするタイミングはリリース計画に合わせて決められます。
一番簡単なリリース計画としては、developブランチに開発済みの機能をすべてリリースすることで、releaseブランチを作るだけで済みます。
但し、同時に複数開発チームがそれぞれ違う機能を開発し、複数回リリースするように計画する場合、先にリリースブランチを作成して、対象となる機能を1つずつマージするようにしましょう。
例えば、feature 1, 2, 3を同時に開発するが、先にfeature 1, 2をリリースし、数週後にfeature 3をリリースする場合:
上記release 1.0, 2.0のようなreleaseブランチは、一旦developから分岐して作成したら、原則的には二度とdevelopから修正ソースコードをマージしない、というルールにしましょう。
理由は、複数回リリース計画がある場合、releaseブランチ作成後、別の機能がdevelopにマージされることがあるので、さらにdevelopからマージしてしまうと、テストが終わっていないにも関わらず誤って機能がリリースされてしまいます。
以下の図のように:
また、featureブランチは開発完了したらすぐにdevelopにマージする訳ではないです。一旦developにマージすると、次回のリリースに含まれますので、
featureブランチをdevelopにマージするタイミングは、リリース計画に合わせて確認しましょう。
リリースの前にバグが見つかった場合
bugfixブランチを該当releaseブランチから分岐して作りましょう。そのうえでバグを修正し、PRを提出しreleaseブランチにマージします。修正されたバグはリリース作業後、releaseブランチがmaster, developにマージされると反映されます。
以下の図の通り:
④ 本番環境のバグ修正
本番環境でバグが発生した場合、以下の手順で修正します。
- まず、masterブランチからhotfixブランチを作成する。
- hotfixブランチにて修正が終わったら、タグを付ける。(命名規則は下記のTag命名規則を参照)
- 本番環境へのデプロイが完了したら、hotfixブランチをmasterとdevelopブランチにマージする。
- マージ完了後にhotfixブランチを削除する。
保守用ブランチ
プロダクトのバージョンアップポリシーにより、マイクロサービス単位でバージョン管理され、各メジャーバージョンに対しては、一定の保守期間があります。ですので、該当マイクロサービスのGitHubリポジトリには、各メジャーバージョンの保守用ブランチを作る必要があります。
例えば、「自動車」というマイクロサービスは、これまでV.1, 2, 3の3つメジャーバージョンがリリースされた場合、保守用ブランチは以下のようになります:
古いメジャーバージョンにおいて、マイナーチェンジや、バグ修正などを行うには、もちろん該当する保守用ブランチから分岐するのですが、開発規模によって適当なリリース計画を作って、併せて開発用ブランチや、リリースブランチなどを決めたらいいです。
Branchコミット規則
Gitのブランチに修正ソースコードをマージするには、2種類の方法があります:
・直接コミットする方法
・pull requestを提出してレビュー担当者が承認してからマージする方法
原則的には、pull requestを作ってからマージする方法を採用しましょう。
但し、以下のブランチには、直接コミットしてもいいです:
1.新機能、修正機能を開発する作業用featureブランチ
2.リリース直前のバグ修正用bugfixブランチ
3.リリース後バグ修正用hotfixブランチ
Tag命名規則
dev環境
1.1 GitHubの上に、手動的にリリース時(非推薦)
→ gitブランチにタグを付ける
命名規則:x.x.x-SNAPSHOT
例:1.0.0-SNAPSHOT
→ ECRに登録する時、イメージのタグはタグ&時間により、自動的に付ける。
イメージのタグ名:x.x.x-SNAPSHOT_yyyyMMdd-hhmmss
例:1.0.0-SNAPSHOT-20210728-154024
1.2 JIRAチケットを利用し、自動的にリリース時(推薦)
→ gitブランチにタグを付けない。
→ ECRに登録する時、イメージのタグは現在のブランチ&時間により、自動的に付ける。
イメージのタグ名:ブランチ名_yyyyMMdd-hhmmss
例:develop-20210728-154024
stg&prod環境
releaseブランチ又はhotfixブランチにタグを手動的に付ける。
命名規則:release.x.x.x
例:release.1.0.0
このGitブランチ戦略で解決した課題
私たちの開発チームは1年前に発足しました。当初、メンバー達の持っている開発経験とバックグラウンドがそれぞれ違うため、ソースコード管理についてかなり混乱していました。
また、同じプロジェクトに本社にいる開発者たちが組んだ「コア」チームと、オフショアにいる開発者達が組んだ「スター」チームがありました。
両チームはそれぞれ違う機能を分担して開発しますが、やはり同じソースファイルを同時に修正することが避けられません。
よって、以下の問題が発生しました:
- ソースコードのコンフリクトが発生する時、誤って他人の修正分を削除してしまう
- 古いソースコードをベースに機能開発してしまう
- 段階的なリリースが実現できない
我々はシステム開発をする上で、チームワークを大事にしています。全員に認められ、そして実行できるルールが不可欠です。
Gitflowはまさにこういうものです。
それぞれ違う機能の開発を担当する人は、それぞれ違うfeatureブランチを作成して、互いに影響しないようにソースを修正できるでしょう。
また、スプリントの開発周期に合わせて最新ソースコードをdevelopブランチに保持することで、次の開発周期がスタートする際に、みんなが最新ソースコードをベースに各自の担当分を展開できるでしょう。
さらに、「リリース計画」ごとにreleaseブランチを作成することで、開発される機能を少しずつリリースすることが実現できますので、開発者の負担を減らすことができ、プロジェクト自身のリスクも減らせるでしょう!
このGitブランチ戦略を導入したことで、私が当初リードしていたバックオフィスシステムの開発チームは混乱期を乗り越えて、安定的に機能開発・リリースすることができました!今後、アプリ開発のプロジェクトマネージャーを担当することになったのですが、アプリ開発でも似たような課題に直面するときに、この経験を参考にして、また改めてチャレンジしてみたいと思っています。皆さんもご自分自身のプロダクト開発に参考してみてはいかがでしょうか?
関連記事 | Related Posts
We are hiring!
【部長・部長候補】/プラットフォーム開発部/東京
プラットフォーム開発部 について共通サービス開発GWebサービスやモバイルアプリの開発において、必要となる共通機能=会員プラットフォームや決済プラットフォームの開発を手がけるグループです。KINTOの名前が付くサービスやTFS関連のサービスをひとつのアカウントで利用できるよう、様々な共通機能を構築することを目的としています。
PjM /システム開発G /東京
システム開発Gについて各国のKINTOビジネスの成長を支援すべく、そのシステムプラットフォームの全体デザイン、設計、開発、導入を担うグループとなります。新しいグローバルプロダクト・プロジェクトに関わり、ゼロイチに関わる機会が存分にあります。