Trunk-Based Developmentは、長期間存続するフィーチャーブランチを使わずに、すべての変更を単一のメインブランチ(trunk)にマージする開発手法です。trunkbaseddevelopment.com、2024年によると、Trunk-Based Developmentは、短期間のブランチ(1〜2日)またはフィーチャートグルを使用したtrunkへの直接コミットを特徴とします。このアプローチはContinuous IntegrationおよびContinuous Deployment(CI/CD)と組み合わされ、マージコンフリクトの数を減らします。
重要なポイント
Trunk-Based Development(TBD)は、すべての開発者が1日に複数回、自分の変更を単一のメインブランチ(trunk、main、master)に統合するバージョン管理手法です。長期間存続するフィーチャーブランチを使用するGit Flowとは異なり、TBDはブランチの寿命を数時間、まれに1〜2日に抑えます。主な目標は、大規模なフィーチャーを数週間の開発後にtrunkにマージする際の「マージ地獄」(merge hell)を回避することです。
Google Cloud DevOps、2024年によると、Trunk-Based Developmentは、高パフォーマンスなDevOpsチームの主要なプラクティスの1つです。State of DevOps Report(Puppet、2023年)は、TBDを使用するチームが障害からの復旧が30%速く、本番環境での重大な欠陥に遭遇する頻度が50%低いことを示しました。TBDはContinuous Deploymentに必須です。
Trunk-Based Developmentは、開発者がレビューなしで直接trunkにコミットすることを意味するわけではありません。TBDでは、MRを作成し、迅速なコードレビュー(数時間以内)を行った後、trunkにマージされる短期間のフィーチャーブランチを使用します。レビューに1日以上かかる場合は、フィーチャーをより小さな部分に分割する必要があります。
年次のState of DevOps Report(Puppet/DORA)は、高パフォーマンスチームのプラクティスを追跡しています。2015年以降、TBDは高いデプロイ頻度(deploy frequency)と低い復旧時間(MTTR)に相関するトップ3のプラクティスに入っています。TBDを実践するチームは、コードを2〜3倍頻繁にデプロイし、障害からの復旧が30%速くなっています(DORA、2023年)。
Feature Toggles(フィーチャーフラグ)は、コードを変更せずに機能を有効または無効にするメカニズムです。TBDでは、フィーチャートグルがフィーチャーブランチを置き換えます。開発者は未完成のコードをtrunkにコミットしますが、条件付きフラグの背後に隠します。機能が公開可能になったら、再デプロイすることなく設定でフラグを切り替えます。
Martin Fowler、2024年によると、フィーチャートグルは4つのタイプに分類されます。リリーストグル(機能の可視性管理)、エクスペリメントトグル(A/Bテスト)、オプストグル(運用パラメータ管理)、パーミッショントグル(ロールベースのアクセス)です。モバイルプロジェクトでは、リリーストグルが特に有用です。新しい機能はリリース日まで隠されていますが、コードはすでにtrunkにありCI/CDを通過します。
// AndroidのKotlinにおけるFeature Toggle
object FeatureManager {
private val remoteConfig = FirebaseRemoteConfig.getInstance()
fun isEnabled(key: String): Boolean {
return remoteConfig.getBoolean(key)
}
}
// コード内での使用
if (FeatureManager.isEnabled("new_checkout_flow")) {
showNewCheckoutScreen()
} else {
showOldCheckoutScreen()
}
Continuous Integration(CI)はTBDの最も重要なコンポーネントです。trunk(またはMR前の一時ブランチ)への各プッシュは、完全なパイプライン(ビルド、単体テスト、統合テスト、リンター、静的解析、コードカバレッジチェック)をトリガーします。少なくとも1つのステージが失敗した場合、作成者は次のコミットの前にコードを修正します。「壊れたtrunkは開発停止」がTBDの主要ルールです。
Jez Humble、Continuous Delivery、2024年によると、Trunk-Based Developmentには10〜15分で完了するCIパイプラインが必要です。ビルドに時間がかかると、開発者のコミット頻度が低下し、TBDの意味が損なわれます。モバイルプロジェクトでは、AndroidとiOSのビルドに20〜30分かかる場合があり、TBDの利便性が低下します。そのような場合、チームは即時CIを備えたShort-Lived Feature Branches(1日ブランチ)を使用します。
# TBD(Android)向けGitHub Actions
name: CI - TBD Check
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: ./gradlew testDebugUnitTest
- name: Static analysis
run: ./gradlew ktlintCheck detekt
短期間ブランチ(short-lived branches)は、純粋なTBD(trunkへの直接コミット)とGit Flowの間の妥協点です。ブランチの寿命は1〜2日以内で、1〜3コミットの変更を含み、レビュー(最大4時間待機)後にtrunkにマージされます。フィーチャーにより多くの時間が必要な場合は、サブタスクに分割され、それぞれが独自の短期間ブランチを持ちます。
TBD Documentation、2024年によると、短期間ブランチのルールは次のとおりです。ブランチは新しいtrunk(1時間以内)から作成され、merge/rebaseによるtrunkとの同期は行われず(4時間以上経過した場合は新しいブランチが作成される)、MR/PRは最初のコミット直後に作成されます(作業が完了していなくてもDraftとして)。
Trunk-Based Developmentでは、pre-tested commitsの手法が重要です。開発者はコミット前に自分のブランチでCIパイプラインを実行し、ステータスがグリーンになった後にのみコミットがtrunkに到達します。GitLabでは、“Merge when pipeline succeeds”オプションを使用したMerge Requestパイプラインを通じて実装されます。GitHubでは、Required status checks付きのブランチ保護ルールを通じて実装されます。これにより、trunkに壊れたコードが含まれることがなくなります。
Branch by Abstractionは、長期存続するフィーチャーブランチを作成せずに、システムの一部を置き換えたり大幅に変更したりできる手法です。Gitでのブランチ作成の代わりに、開発者は抽象化(インターフェース)を作成し、その下で古い実装と新しい実装の両方が動作します。徐々にすべてのコンシューマーが新しい実装に移行され、その後古い実装が削除されます。
Branch by Abstraction、2024年によると、Branch by Abstractionの段階は次のとおりです。1)置き換え対象のコンポーネントの抽象化を作成する、2)抽象化の下で新しいバージョンを実装する、3)設定を介してコンシューマーを新しい実装に切り替える、4)古い実装を削除する。すべてのステップは、それぞれがCI/CDを壊さない小さな部分でtrunkにコミットされます。
Trunk-Based DevelopmentとGit Flowは、ブランチ管理に対する2つの対照的なアプローチです。Git Flowは長期存続ブランチと厳格な階層構造を使用し、TBDは単一のブランチと短い統合サイクルを使用します。どちらを選択するかは、チームサイズ、リリース頻度、CI/CD自動化のレベルによって異なります。
| パラメータ | Trunk-Based Development | Git Flow |
|---|---|---|
| ブランチ | 1つ(trunk)+ short-lived | 5タイプ(main, develop, feature, release, hotfix) |
| ブランチの寿命 | 数時間〜1日 | 数日〜数週間 |
| フィーチャーブランチ | 推奨されない | 主要なメカニズム |
| Feature Toggles | 必須 | オプション |
| CIの必須性 | 絶対 | 推奨 |
| Continuous Deployment | 互換性あり | 困難 |
| 複雑さ | 低い | 高い |
TBDの間違いは、ほとんどの場合、不十分なCI/CDまたは弱いコミット規律に関連しています。最初の間違いは、CIなしでTBDを導入することであり、最初の失敗したコミットで破綻します。trunkを15分以内に修正できない場合、チームはプロセスへの信頼を失い、長期ブランチに戻ります。2つ目の間違いは、「このフィーチャーだけ」という理由で長期存続ブランチを許可することであり、これによってコンセプト全体が破壊されます。
Paul Hammant、2023年によると、3つ目の間違いはコードのモジュール性の低さです。Trunk-Based Developmentでは、コードが独立したモジュールに分割されている必要があります。1つのクラスの変更が他の3つのモジュールを壊す場合、開発者は小さな部分でコミットできません。4つ目の間違いは、フィーチャートグルを無視することです。フラグなしで未完成のコードをコミットしようとすると、チーム全体のtrunkが壊れます。
Trunk-Based Developmentは、モバイルプロジェクトでは、ビルド時間の長さ(AndroidとiOSで20〜30分)と厳格な品質要件のために特有の特徴があります。GoogleとSpotifyはモバイル開発でTBDを使用しており、マージ前に必須のCIを通過する短期間ブランチを適用しています。フィーチャートグルは、Firebase Remote ConfigまたはLaunchDarklyを通じて管理されます。
LaunchDarkly Docs、2024年によると、モバイル開発ではTBDに利点があります。機能はリリース日より前にtrunk内で他のコードと一緒にテストされ、統合の問題のリスクが軽減されます。CIパイプラインに15分以上かかる場合は、各プッシュで自動CIを実行する1日の短期間ブランチが最適です。Apple App StoreとGoogle Playでは、TBDはフィーチャートグルを使用した段階的ロールアウトの設定を必要とします。
TBDでのフィーチャートグル管理には、プラットフォームが使用されます。LaunchDarkly(エンタープライズ、フル機能)、Firebase Remote Config(小規模プロジェクト向け無料)、Split.io(オープンソース)です。これらは、ユーザー割合に基づくターゲット機能有効化、A/Bテスト、使用状況監視、エラー時の自動無効化を提供します。モバイルプロジェクトでは、Firebaseとの統合と最大1000ユーザーまでの無料枠により、Firebase Remote Configが最も人気のある選択肢です。
よくある質問
Trunk-Based Development(TBD)は、すべての開発者が単一のメインブランチ(trunk)で作業し、1日に数回小さな単位でコードをコミットするアプローチです。これによりマージコンフリクトが減少し、Continuous Integrationが高速化されます。
TBDでは、長期存続するフィーチャーブランチや独立したdevelopブランチはありません。すべての変更は迅速にtrunkにマージされ、未完成のコードはフィーチャートグルの背後に隠されます。Git Flowは長いブランチと、releaseやhotfixを通じた厳格なマージプロセスを使用します。
はい、フィーチャートグルはTBDの重要なメカニズムです。メインブランチを壊すことなく、未完成のコードをtrunkにコミットできます。機能はフラグの背後に隠され、準備ができたときに有効化されます。これにより、Git Flowのフィーチャーブランチが置き換えられます。
CI/CDから始めます:パイプラインは15〜30分で完了する必要があります。フィーチャートグル(Firebase Remote Config、LaunchDarkly)を導入します。迅速なコードレビューとともに1〜2日の短期間ブランチを使用します。大規模なフィーチャーは小さなサブタスクに分割します。
主なリスクは、壊れたtrunkがチーム全体をブロックすることです。高速なCI(10〜15分)と小さなコミットの規律なしでは、TBDは機能しません。また、高品質なモジュラーアーキテクチャとフィーチャートグルの経験も必要です。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。