トランクベース開発とは? 本番を守る実践ガイド

要約

トランクベース開発は、全員が短命のブランチで小さな変更を1日1回以上メインへ統合し、常にリリース可能な状態を保つ方式です。成立には、短いCI、信頼できるテスト、速いレビュー、フィーチャーフラグが必要です。フラグは期限付きの負債として管理し、マージ後数分以内に回帰を見つけられる観測体制を整えてから導入してください。

木の幹に短い枝が合流している、トランクベース開発を表すイメージ

午前3時、リリース用のブランチがマージできません。3週間前に作られた40個のコミットが、mainと同じファイルを書き換えています。その痛みこそが、トランクベース開発を考える理由です。トランクベース開発とは、チーム全員が小さな変更を1つの共有ブランチ(トランクまたはmain)へ少なくとも1日1回統合し、そのブランチを常にリリース可能な状態に保つ開発モデルです。

この記事は、Gitには慣れているプラットフォームエンジニアとSREに向けたものです。このモデルが何を求め、何から守ってくれ、どこで静かに壊れるのかを整理します。

トランクベース開発を運用の言葉で言うと何か

定義を制約まで削ってみます。全員が1つのブランチに統合します。その他のブランチが生きる時間は、数週間ではなく数時間です。トランクはすべてのコミットでビルドとテストを通すため、いつでもリリースできます。

DORAの能力ページは、これを数字で示しています。リポジトリ内のアクティブなブランチは3つ以下、トランクへのマージは少なくとも1日1回、コードフリーズなし、ビルドとテストは数分で完了する、という基準です。この数字こそが重要です。このモデルはブランチの書き方の好みではなく、フィードバックループの予算なのです。

深夜のデスクにあるノートPCのターミナルと、点灯したスマートフォンの通知

小規模なチームはトランクに直接コミットすることもあります。大きめのチームは、レビューとビルドチェックのために短命のブランチとプルリクエストを使いますが、統合を遅らせる目的では使いません。trunkbaseddevelopment.comの解説は両方のやり方を紹介しており、Googleが約35,000人の開発者を1つのモノレポのトランクで運用している例も挙げています。

長命ブランチが予測可能なタイミングで壊れる理由

機能ブランチは借金です。利息はマージコンフリクトで、メインに変更が入るたびに膨らみます。ブランチが長く生きるほど差分は大きくなり、差分が大きいほど誰も丁寧に読まなくなります。

これは変更失敗率に直接響きます。2,000行のマージは流し読みされて承認されます。60行のマージは実際に読まれます。レビュアーは怠けているのではなく、注意力を配分しているのです。レビューの質を保てる仕組みは、小さなバッチしかありません。

2つ目のコストは、リリースまで見えません。個別にCIを通過した2つのブランチでも、統合したときに互いを壊すことがあります。それが分かるのは統合の時点、つまり締め切りが迫った最悪のタイミングです。

トランクを信頼する前に必要なもの

サポートする実践なしにトランクへ移行すると、四半期以内に機能ブランチへ戻ることになります。先に4つ揃えておく必要があります。

どれか1つでも欠けると、トランクは壊れたものが蓄積する場所になってしまい、壊れたものを捕まえる場所にはなりません。

未完成の作業を、出荷せずにマージするには

懐疑的な人が必ず聞く質問です。答えは地味です。デプロイとリリースを切り離すのです。コードは本番に無効化された状態で届きます。誰に見せるかは、フラグが決めます。

// checkout.ts
import { flags } from "./flags";

export async function renderCheckout(user: User) {
  if (await flags.isEnabled("new-payment-flow", { userId: user.id })) {
    return renderNewPaymentFlow(user); // トランクにマージ済み、デフォルトは無効
  }
  return renderLegacyCheckout(user);
}

新しいフローは初日にマージされ、フラグはオフのままです。まず社内ユーザーに、次に1%、10%とフラグを切り替え、各段階でSLOのゲートを通します。エラー率が予算を超えたら、フラグをオフにするだけで、デプロイなしに実質的な巻き戻しが完了します。ホスト型のフラグサービスを評価するチームは、LaunchDarklyから検討を始めることが多いです。ただし、このパターンはどのプロバイダーでも、自社の設定ストアでも機能します。

2つ目の手法は、大きなリファクタリング向けのbranch by abstractionです。インターフェースを導入し、呼び出し元をそのインターフェース経由にし、新しい実装をその裏に作り、準備ができたら切り替えます。長命のブランチも、大きなビッグバンマージも不要です。

壁のスイッチが並んでおり、一部はオン、一部はオフの状態

正直なコスト:フラグには半減期のある負債がある

カンファレンスではあまり語られませんが、追加したフラグはすべて、誰かが削除しなければならない本番環境の条件分岐です。80人規模のエンジニアリングチームが、テストしきれない古いフラグを数百個抱えている例も見てきました。

フラグは、期限付きの短命なものとして扱ってください。作成時に担当者と有効期限を決めます。期限を過ぎたフラグにはアラートを出します。フラグを削除するプルリクエストの中で、不要になったコードパスも一緒に削除します。

組み合わせのリスクも現実です。独立したboolean型のフラグが10個あると、1,024通りの設定になります。すべてをテストすることはできません。フラグ同士の相互作用は少なく保ち、リリース用のフラグと、キルスイッチのような長期の運用トグルは分けて管理してください。

トランクの上でのリリース戦略

トランクからリリースを切る一般的な方法は2つあり、どちらも長命のブランチを必要としません。

どちらを選ぶかは、検知時間で決まります。悪いデプロイを5分以内に気づき、2分以内に戻せるなら、前に進めて修正すれば十分です。平均検知時間が1時間なら、リリースブランチが踏みとどまれる足場になります。

短い支線が1本の本線に合流する鉄道の線路

オブザーバビリティは取引のもう一つの半分

トランクベース開発はデプロイ頻度を上げるので、何かが壊れうる瞬間の数も増えます。このモデルが機能するのは、マージから数分以内に回帰を見つけられる場合だけです。特定のリリースに紐づくエラー率、レイテンシのパーセンタイル、リソースの飽和度が必要です。月曜日に誰かがチェックするダッシュボードでは足りません。

有効なテストがあります。マージ後に「この変更でp99かエラー率が動いたか」を、5つのタブを開かずに答えられますか。答えられないなら、1日に何度もマージする準備はまだできていません。

どのスタックを使っていても、要件は同じです。グラフにデプロイのマーカーがあること、SLOのバーンレートのアラートがあること、疲れた人が午前3時にも迷わず実行できる巻き戻しの経路があることです。

トランクベース開発、GitFlow、GitHub Flowの違い

3つは混同されがちなので、1つの性質で区別します。作業が共有ブランチから離れている時間です。

すでにGitHub Flowで、2日以内に終わるブランチを回しているチームは、思う以上にトランクに近いです。足りないのは通常ツールではなく、フラグの規律とレビューのリードタイムです。

最初に動くDORA指標

始める前に計測してください。さもないと、後から感覚で議論することになります。デプロイ頻度と変更のリードタイムは最初に反応します。小さなバッチがパイプラインをより速く流れるからです。変更失敗率と復旧時間はそのあとに続きますが、これはブランチ戦略だけでなく、オブザーバビリティと巻き戻しの経路に依存します。

数字を個人の評価表にしないでください。数字が示すのはシステムです。リードタイムが伸びたら、人を見る前にレビューの待ち行列とCIの時間を確認してください。

トランクベース開発が間違った選択になるとき

いくつかのケースでは、導入を見送るか、少なくとも遅らせるべきです。どのケースに当てはまるかを正直に判断してください。

トランクベース開発は、何かを保証するものでもありません。DORAの知見は2016年と2017年のデータに基づく相関です。これらの実践に従うチームは、より良い提供力と運用パフォーマンスを示しました。ブランチ名を変えればパイプラインが直る、とはいっていません。

ビッグバン移行をせずに始めるには

ポリシーを発表しないでください。まず計測し、それから小さくしていきます。

  1. 現在のブランチの寿命と、プルリクエストの中央値サイズを記録します。これがベースラインになります。

  2. 上限を設定します。例えば2日を超えるブランチは作らない、というルールです。ダッシュボードで見えるようにします。

  3. CIの最も遅い部分を直します。ビルドに30分かかるなら、ほかのことはまだ重要ではありません。

  4. 1つの実際の機能に1つのフラグを導入します。無効な状態で出荷し、1スプリント以内に削除します。

  5. コードフリーズは最後に外します。巻き戻しの経路を、本当に一度使ってからです。

1か月後にもう一度レビューしてください。最初に動く数字は、通常プルリクエストのサイズとマージまでの時間です。変更失敗率には時間がかかり、問題が早く見えるようになるため、一時的に悪化することもあります。

あなたのポストモーテムは、ブランチ戦略について何と言うでしょうか

ポストモーテムには何と書かれるでしょうか。これが、出荷前に問うべき有用な質問です。直近のインシデントが、誰もレビューできなかったマージ、3週間乖離したブランチ、40件の変更をまとめたリリースに起因していたなら、その負債がどこで支払期限を迎えるかは、すでに分かっています。

直近の3件の障害を見直してください。大きく、遅いタイミングでの統合が関係していたものは何件ありましたか。その件数が、トランクベース開発に投資する根拠になります。

よくある質問

トランクベース開発とは何ですか?
全員が小さな変更を共有ブランチへ1日1回以上統合し、そのブランチを常にリリース可能に保つ開発モデルです。長命の機能ブランチを置かないことが特徴です。
トランクベース開発とGitHub Flowの違いは何ですか?
GitHub Flowも短命のブランチを使いますが、ブランチの寿命への要求は緩やかです。トランクベース開発はブランチの寿命に最も厳しく、未完成の作業にはフィーチャーフラグかbranch by abstractionを前提とします。
未完成の機能はどうやってマージすればいいですか?
フィーチャーフラグを使い、デプロイとリリースを切り離します。新しいコードは無効な状態で本番に届き、社内ユーザー、1%、10%と段階的に有効化します。
DORAの基準では、どのくらいの頻度でマージすべきですか?
DORAの能力ページは、トランクへの統合を少なくとも1日1回とし、アクティブなブランチは3つ以下、コードフリーズなし、ビルドとテストは数分で終わることを挙げています。
トランクベース開発に向いていないのはどんなときですか?
テストが1時間以上かかり並列化できない場合、顧客が何年も古いバージョンを使い続けて保守用ブランチが必要な場合、フラグの仕組みがない場合、チームがビルドを信頼していない場合です。
導入はどこから始めればいいですか?
まずブランチの寿命とプルリクエストのサイズを計測します。次に2日などの上限を設け、CIの最も遅い部分を直し、1つの機能で1つのフラグを試します。