📝

main以外のブランチは必要か?【ブランチ管理について考察

に公開

ブランチ管理をリスクとコストで考える

ブランチ管理にはGit Flow、GitHub Flow、Trunk-Based Developmentなど、いくつかの定番の種類が存在する。
本記事ではこれら手法について、プロジェクトにおけるリスクとコストという観点から考察してみる。

主要なブランチ管理の種類

1. Git Flow

主要ブランチ:
main: 本番環境用の安定ブランチである。
develop: 次回リリース用の開発ブランチである。
feature/: 新機能開発用のブランチ(developから分岐)である。
release/
: リリース準備用のブランチである。
hotfix/*: 本番環境の緊急修正用ブランチである。

特徴: 構造化されたワークフローで、大規模プロジェクトやリリース管理が重要な場合に適している。

2. GitHub Flow

主要ブランチ:
main: 常にデプロイ可能な状態を保つ。
※機能や修正ごとにfeature/*やfix/*などのブランチを作成し、プルリクエストでmainにマージする。

特徴: 継続的インテグレーション(CI/CD)に最適化され、シンプルなワークフローを重視する。

3. Trunk-Based Development

主要ブランチ:
main: 常に本番品質を保つ。
※短期間のfeatureやfixブランチを作成し、すぐにmainにマージする。

特徴: CI/CDと相性が良く、GoogleやFacebookなどの大規模チームで採用される。

補足:GitHub FlowとTrunk-Based Developmentの違い

  • トランクベース開発はmainブランチに全員がこまめに統合する。featureブランチは使ってもすぐ消す。

  • GitHub Flowは「main+featureブランチ」でPRによるレビュー・マージを軸に据えており、featureブランチが長命になることも許容する。

  • トランクベース開発では「未完成機能もmainにマージ」し、feature flagなどで本番公開を制御する。

考察

そもそもなぜブランチを作るのか

ブランチを作る動機は大きくは以下の通りだろう。

  1. 並行開発のサポート
    • 複数の機能やバグ修正を同時に進めたい場合、1つのブランチで作業すると変更が衝突しやすくなる。ブランチを作成すれば、チームメンバーが独立して作業でき、後で統合できる。
  2. 実験やプロトタイピングの安全性
  • アイデアを試す際、メインコードを壊したくない場合にブランチを使える。失敗してもメインに影響せず、簡単に破棄できる。
  1. リリース管理と安定性の確保
    • 本番環境用の安定したコードを保ちつつ、開発用の変更を分離できる。

いくつかの観点からブランチを作る理由を書いてみたが、その本質的な問題はこの1点にとどまるのではないだろうか?

  • 既存のコードを壊すリスクを避けたい

ではコードを守ってくれるものは何か、その観点からも考察してみる。

ブランチがコードを守ってくれるのか?

これまでの考察から、ブランチを作る理由は既存のコードを守るためといえそうだ。
では、「ブランチ」がコードを守ってくれてるのだろうか?

コードが破壊されてしまう状況から考えてみる。
コードが破壊が起きてしまう瞬間とはいつか。

それは問題のあるコードを既存のものにコミットしたときである。
ここで強調しておきたいのは、問題をあるコードを書いてたときではなく、そのコードをコミットするという作業をした瞬間にコードが破壊されることである。
つまりコードを書くこと自体はまったく問題ではない。

ここでブランチの機能を今一度確認する。
ブランチはあくまで、コードを分岐し、作業場所を提供しているだけであり、問題のあるコードをコミットさせないという能力はそれ自体にはない。

ブランチそのものはコードを守っているとはいえない

それでは、なぜコードを守るためにブランチを作るつもりになっているのか。

ブランチの作成はリスクの後回し?

開発者は、ブランチを作成し、新しい機能の追加やバグ修正を独立して進めている。

ブランチを作成する主な動機は、既存のコードを破壊したくないという思いから生じているが、実際のところは、破壊してしまう可能性のあるタイミングを遅らせるための手段として機能しているのが本質的なところではないだろうか。

結果として、ブランチ作成は、リスクを「回避」するのではなく「後回し」にする戦略だといえる。

本当にコードを守ってくれるもの

実際にコードの品質と安定性を保証し、破壊から守るのは、テストと検証のプロセスである。
その中心となるのが継続的インテグレーション(CI)と継続的デリバリー(CD)のパイプラインだ。
CIは、開発者がコミットするたびに自動テストを実行し、問題の早期発見に貢献する。
CDは、CIによって検証されたコードのみをデプロイ可能にする仕組みであり、本番環境への安全なリリースを担保する。

これらの自動化されたテストと、それに付随するレビューや手動デバッグといった品質保証活動こそが、コードの健全性を維持する本質的な防御機構なのである。

リスクの後回しはよくない

リスクを後回しにすることは、長期的に見ればプロジェクト全体のコストを増大させる要因となる。
特にブランチの寿命が長くなるほど、メインブランチとのコードの乖離は大きくなり、マージ時のコンフリクト発生確率が高まる。

これらのコンフリクトを解決するには、複数の変更点を慎重に分析し、整合性を保つための時間と労力が大量に必要とされる。

さらに、問題が統合段階で発見された場合、原因特定や修正にかかるデバッグコストも早期発見の場合と比較して格段に高くなる傾向がある。

結論

常に本番品質のコードを保証するという究極の目標を追求するのであれば、mainブランチ以外の永続的なブランチは本質的に必要ないと考えられる。

機能開発やバグ修正は、mainブランチから短期間で分岐させ、変更が完了次第すぐにmainへマージするトランクベース開発のアプローチが理想的である。
この戦略では、コードの統合頻度を最大化し、コンフリクトや乖離によるリスクを最小限に抑えることができる。

ただし、プルリクエストによるコードレビューや自動テストのトリガーとして一時的なブランチを作成することは、品質保証の観点から推奨される。
これらのブランチはあくまで一時的な作業空間であり、レビューとテストが完了次第、速やかにmainブランチに統合され、削除されるべきだ。

したがって、永続的な意味での開発ブランチは不要であり、mainブランチが常に信頼できる唯一のソースとなるべきである言えるのではないだろうか。

Discussion