PR

私がGit Flowに惹かれ、そして離れていった理由

git ブランチ戦略を考える ソフトウェア

はじめに

リリース、保守上の複雑な要件を、Git操作やブランチモデルで解決しすぎていないでしょうか?

私はこれまでの開発経験で、様々なGitの運用方針(ブランチ戦略)を経験してきました。シンプルなものから複雑なもの、あるいは独自の運用方針も含めれば千差万別です。

私は組み込みやPCのネイティブアプリ等、ややレガシーとされる分野の経験が多く、そこではGit Flowなどの複雑な方針が今でも多く使われており、それ自体は問題ない(むしろ厳密に管理できるメリットがある)と考えていました。

しかし最近はシンプルな運用方針で、世間一般的に使われているもの(例:GitHub FlowやTrunk Based Development)をなるべくそのまま採用するのがいいのではないか、と考えるようになりました。

その理由について書いていきます。

複雑な運用(例:Git Flow)の限界

複雑な運用方針の代表例として、Git Flowを取り上げます。

Git Flowはmaster(main), develop, feature, hotfix, releaseの5つのブランチを組み合わせた運用方針で、大規模でリリースサイクルが比較的長く、リリースを厳密に管理したいプロジェクトに向くとされる方針です。

Gitflow ワークフロー | アトラシアン Git チュートリアル
Gitflow ワークフローについて詳しく見ていきます。この包括的なチュートリアルで、この Git ワークフローが自身と自身のチームにとって最適かどうかを確認してください。

亜種も含めれば今でも現役のプロジェクトも多いかと思いますが、Web系を中心に近年はGitHub FlowやTrunk Based Developmentなどのシンプルな運用に主流が移りつつあり、レガシーな運用と言われることもあるようです。

Gitflow とは、元来は Git ブランチを管理するための破壊的で斬新な戦略のレガシー Git ワークフローです。Gitflow の需要は落ち込み、トランク ベースのワークフローが利用されるようになっています。

Gitflow ワークフロー | アトラシアン Git チュートリアル

この引用をもってGit Flowがダメだと言うつもりはありません。

私の視点からはまだまだ採用例もたくさんありますし、むしろレガシーなプロジェクトには合うと長らく考えていたのですが、一方で最近はうまくプロジェクトにフィットしないと感じることも増えてきました。

複雑さゆえの学習コスト

近年のGit Flowへの批判で多いのは「複雑すぎる」ということです。

新機能開発時にdevelopからfeatureの分岐、プルリクエストによるdevelopへのマージ、ここまでは難しいことはありません。多くのブランチ戦略で似た動きは含まれています。

しかしhotfixブランチやreleaseブランチの運用は結構特殊で、学習コストが高くなります。

慣れている方、特に運用方針を策定する方にとっては「別に難しくはない」と感じるかもしれませんが、チーム開発の場合メンバーのGitのスキルもまちまちだったりして「学習コストの高さ」が運用ミスや手戻りに繋がるリスクは考えておくべきだと思います。

私自身比較的レガシー寄りの開発を経験することが多かったためか、Gitの経験や習熟度がメンバーによって大きく異なるチームも経験してきました。そのような環境では、運用方針そのものが高度であることよりも、チーム全体が無理なく理解・運用できることの方が重要だと思います。

複雑な要件の下ではより複雑化しやすい

そして、Git Flowは厳密でありながら柔軟な運用もできるが故、自然と履歴が複雑化し、管理コストが増大していくことがあります。

Git Flowが理想的に機能するような、developで開発を続けて、安定しているのが確認できればreleaseを介してmasterへ、という運用がされていれば(前述のような学習コストの問題を除けば)そう大きな問題は発生しないと思います。

ただ現実的には「次のリリースはこの機能だけ入れて出しましょう」というような特別なリリース要件が発生することがあります。developに既に他の機能もマージされているような場合、これは恐らく標準的なGit Flowでは想定していない流れですが「特定のコミットからreleaseを分岐する」とか「releaseブランチ上で特定のコミットだけcherry-pickやrevertする」といった対応をすることになります。

ただこのようなことをし始めると履歴はどんどん複雑になっていきます。悪化していくと「masterが今どういう状況なのかよくわからない」というようなことになり、正しく機能をマージ、リリースできていなかったというような事故にも繋がりかねません。

Git Flowは大規模でリリースが厳密に管理されるようなプロジェクトに向くとされ、だからこそ採用されるわけですが、そのようなプロジェクトでは実際にリリース要件が複雑化することがあります。そしてGit Flowはそのような要件も(ある意味無理やり)対応することができてしまうため、複雑な要件をGit上で表現することに進みやすく、履歴が複雑化しやすいと感じています。

そうすると、管理のために導入したブランチ戦略が、複雑すぎて管理コストを生むという状況になりかねません。

シンプルな運用(例:GitHub Flow, Trunk Based Development)

現在、GitHub FlowやTrunk Based Developmentなどのシンプルな運用が主流になりつつあるようです。

GitHub Flowを例にすると、masterからfeatureブランチを分岐しプルリクエストでレビューしてmasterにマージするというシンプルなものです。

最大のメリットは、わかりやすいこと。学習コストも低くチーム全体の理解度を上げられ、グラフもシンプルなので管理者の立場からも今どの作業がどう進んでいるかを把握しやすく運用上のミスが起こりにくいでしょう。

「シンプルなだけに、できないことも多いのでは」と思われるかもしれません。それは事実です。ただ前述のようにGit Flow等の運用は柔軟故に複雑になりすぎ、管理コストが上がるのが課題だと思います。

複雑な要件そのものを無くせるわけではありません。ただそれをGitのブランチ構造や操作だけに頼らず、コードの方で表現したり、CI/CDなど別の方法で表現する方が、結果的にシンプルで見通しがよくなると感じています。

例えばアップデートに際して新機能を有効化するかどうかという問題に対して、Trunk Based Developmentなどでは機能フラグというアイデアを使うことがあります。

Jira の機能フラグ ソリューション | Atlassian
フィーチャー フラグは、チームがコードを追加することなく変更を加えることを可能にするソフトウェア手法です。メリットやユース ケースなどについてご覧ください。

Gitの履歴やブランチ構造は開発者が日常的に確認するものです。そのためGit履歴自体は可能な限り単純に保っておき、他の仕組みも使ってプロジェクト全体の要求を表現するようにすることには大きな価値があると思います。ソフトウェアの基本通り、適切な粒度と場所に分けるということです。

旧バージョンの長期保守などは、よくGit Flowに求められるニーズかもしれません。ただこちらも、シンプルな運用に特定バージョンの保守用ブランチを足すなどして対応することはできます。

もちろんそれが複雑化していった結果「最終的にGit Flowが出来上がった」みたいなことはあるかもしれません。ただ、多くの場合まずはシンプルな運用をベースに必要最小限のルールを追加する方が理解しやすいと感じています。

必要なものは必要になった時に足す、逆に不要になったものは整理する、などでシンプルさを保つほうが良い結果になりやすいと思います。(もちろん理想であって、実際の現場での継続した整理がどれだけ難しいか重々承知しておりますが…)

独自の方針について

まったく独自の運用方針を採用したり、何らかの方針をベースに改良を加えることもよくあると思います。

これも私の最近の考えでは最低限にとどめ、可能であればGitHub FlowやTrunk Based Developmentのようなシンプルな運用をそのまま採用することから始めるのが良いと感じています。理由としては

  • 基本的にはルールが少ないほど学習コストが低下する。
  • 世間的に名前がついている戦略であれば新規メンバーにも説明しやすく、属人性が低下する。
  • 「ある問題が発生した場合にどうするか」の回答が既に世の中にある場合が多い。

現プロジェクトの要求が複雑に見えても、実はシンプルな既存の方針で対応できないか考えてみる、ルールを追加する場合も必要最低限で、メンバーがすぐ確認できるようにすることが重要だと思います。

結論

  • 学習コスト、複雑化の観点から、運用方針は可能な限りシンプルな方が良い。
  • 独自ルールについては、無くて済むならその方が望ましい。

具体的には、GitHub FlowやTrunk Based Developmentで十分ならそうした方がよく、そこで対応できない要求についてはGit操作のみに頼らず、コードやCI/CD、はたまた開発プロセスの見直しなど別の解決策を考えるのがよいのではないか、というのが現在の私の考えです。

大規模、品質要件が高い、ウォーターフォールを採用するなど、伝統的な開発においてはまだGit Flowなどの複雑な方針も現役だと思います。ですが

「そういった案件だからきちんとやろう」→「複雑なブランチ戦略を採用しよう」

というのは、結果的に管理コストが増大する可能性があります。複雑な要件があることと、複雑なブランチ戦略を採用することは別だと感じています。

大規模な開発で、ただでさえ認知的なコストが高いプロジェクトほど、シンプルな運用のほうが結果的に全体を把握しやすくなり品質が向上するのではないかと思います。

コメント

タイトルとURLをコピーしました