Gitブランチ戦略の選び方:trunk-based vs git-flow と rebase/merge使い分け
個人とチームでGitのブランチをどう切るか。trunk-based developmentとgit-flowの違い、rebase/mergeの使い分け、コミット粒度、Claude Code併用の運用を実例で整理。
ブランチを切らずに main で直接コミットを重ねていた頃、僕は週に一度はやらかしていました。
金曜の夜に「とりあえず動いた」を main へpushして、月曜に別の機能を触ったら、先週の未完成コードが混ざっていて何が原因か追えない。差分を1つずつ git log で遡る作業に、午前中が丸ごと消える。あの時間は本当にもったいなかった。
ブランチ戦略って、最初は「お作法」だと思っていました。でも実際は違います。「失敗しても戻せる単位」を先に決めておく仕組みなんですね。どこで枝を分け、いつ本流に戻し、履歴をどう残すか。これを決めておくと、AIに実装を任せて差分が一気に増えても、後から落ち着いて読み解けます。
この記事では、trunk-based development と git-flow の違いから、rebase と merge の使い分け、コミットの粒度、そしてClaude Codeと一緒に使うときのブランチ運用まで、手元で試せる形でまとめます。コンフリクトを解く手順そのものはClaude CodeでGitコンフリクトを安全に解決するに詳しく書いたので、ここでは「戦略」に絞ります。
この記事の要点
- ブランチ戦略は「お作法」ではなく、戻せる単位を決める設計。先に決めるとレビューも復旧も速い。
- 個人や小さなチームは trunk-based development(短命ブランチ+頻繁マージ)が事故りにくい。リリース管理が重いプロダクトだけ git-flow を検討する。
- rebaseはpush前のローカル履歴の掃除だけ。共有済みブランチには使わない。これがGit公式の鉄則。
- コミットは「1コミット=1つの意味」。理由は本文(body)に残す。
- Claude Codeに任せると差分が膨らむので、slug/機能単位の短命ブランチ+対象外の明記で範囲を固定する。
ブランチ戦略は「戻せる単位」を決めること
ブランチを切る本当の理由は、見た目をきれいにするためではありません。「ここまでは捨ててやり直せる」という単位を作るためです。
たとえば1本のブランチに3つの機能を詰め込むと、そのうち1つが失敗したとき、残り2つも巻き添えで戻すしかなくなります。逆に機能ごとに枝を分けておけば、失敗した枝だけ削除して、他は無事に残せる。引っ越しのときに荷物を1つの巨大な箱に詰めるか、中身ごとに小分けするかの違いに似ています。小分けしておけば、割れ物だけやり直せる。
Claude Codeのようにファイルをまとめて書き換えるツールを使うと、この「戻せる単位」がさらに効いてきます。AIに実装を任せると差分は一気に増えます。どの変更を1つのコミットに入れるのか、どこでレビューを止めるのかを決めていないと、後で原因調査に時間を失う。だから「賢いプロンプト」より先に、ブランチの切り方を決めるほうが事故が減るんです。
考えるポイントは3つだけです。
- どこで枝を分けるか(機能・修正・記事のslug単位か)
- いつ本流に戻すか(毎日か、機能完成時か)
- 履歴をどう残すか(マージで枝を残すか、rebaseで一直線にするか)
この3つの答えがそのまま「ブランチ戦略」になります。
trunk-based development とは何か
最近の主流は trunk-based development(トランクベース開発)です。trunk(幹)と呼ぶ1本の主ブランチを中心に、全員がそこへ頻繁に変更を合流させる進め方です。
Git公式に近い定義サイト trunkbaseddevelopment.com では、ブランチについてこう言い切っています。「mainline/main/trunk から分かれた共有ブランチは、どんなリリース頻度でも良くない」。長く生き続ける開発ブランチを避け、機能ブランチはコードレビューとCIのためだけに短命で使うのが原則です。
ここでいう「短命」は、感覚的には1日から数日です。開発者は少なくとも1日1回は trunk へ変更を取り込む。だから枝が古くなりにくく、本流との差が小さいうちにマージできる。コンフリクトが起きても傷が浅いんです。
僕が個人開発でこれに切り替えてから、月曜の「先週の自分は何をしていたのか問題」がほぼ消えました。枝が長生きしないので、未完成コードが本流に近づかない。短い枝を切って、終わったら畳む。これの繰り返しです。
# trunk-based の基本サイクル:短い枝を切って、すぐ畳む
git fetch origin
git switch main
git pull --ff-only origin main # 本流を最新に
git switch -c feature/coupon-validation # 短命ブランチを切る
# ここで小さく実装してコミット
git switch main
git pull --ff-only origin main # 戻る前にまた最新化
git merge --no-ff feature/coupon-validation
git push origin main
git branch -d feature/coupon-validation # 役目を終えた枝は削除
git-flow との違いと、どちらを選ぶか
もう一方の有名な型が git-flow です。main、develop、feature/*、release/*、hotfix/* と役割の違うブランチを複数並べ、リリースを段階的に管理します。
git-flow が向くのは、バージョンを明示してリリースし、複数バージョンを並行保守するようなソフトです。インストール型のアプリや、契約でサポート期間が決まっているプロダクトですね。逆に、Webサービスのように「常に最新の1本を本番へ出す」開発では、develop と main の二重管理がただの手間になりがちです。
両者を並べると違いがはっきりします。
| 観点 | trunk-based development | git-flow |
|---|---|---|
| 中心ブランチ | main(trunk)1本 | main と develop の2本 |
| 機能ブランチの寿命 | 1日〜数日(短命) | 機能完成まで(長くなりがち) |
| マージ頻度 | 毎日のように本流へ | 機能単位でまとめて |
| コンフリクト | 浅く・少ない | 枝が育つと深くなりやすい |
| リリース | 常に最新を出す前提 | バージョンを切って段階的に |
| 向くチーム | 個人〜中規模、Web中心 | 並行バージョン保守、リリース重め |
| AIとの相性 | 良い(差分が小さく追える) | 枝が育つと差分が膨らみやすい |
迷ったら trunk-based を選ぶのが無難です。理由はシンプルで、枝が短いほど事故の影響範囲が小さいから。git-flow は強力ですが、運用ルールが多く、小さなチームだと持て余します。「うちは並行バージョンを保守している」とはっきり言える場合だけ git-flow を検討する、くらいの温度感がちょうどいいです。
rebase と merge の使い分け
ここが一番つまずきやすいところです。結論から書くと、rebaseはpushする前のローカル履歴の掃除だけに使う。これがGit公式の鉄則です。
Git公式ドキュメントは、はっきりこう書いています。「すでにリポジトリの外に存在し、他の人がそれを土台に作業しているかもしれないコミットを、rebaseしてはいけない」。共有済みのコミットをrebaseすると、似ているが別物のコミットに作り替えてしまい、他の人が次にpullしたときコンフリクトと履歴の重複が起きます。
使い分けは2つだけ覚えれば十分です。
- merge:枝を本流に合流させて、分岐の事実を履歴に残す。複数人が触る共有ブランチ向き。
- rebase:自分のローカルコミットを最新の
mainの上に積み直して、履歴を一直線にする。まだpushしていない枝だけ。
具体的には、自分の作業ブランチをpushする前に「コミットがごちゃついてきたな」と思ったら、ローカルでrebaseして整える。これはOK。
# pushする前のローカル掃除:自分の枝を最新mainの上に積み直す
git fetch origin
git switch feature/coupon-validation
git rebase origin/main
# コンフリクトが出たら解決して continue(解き方は下の関連記事へ)
git rebase --continue
# 違和感があれば全部やめて元に戻せる
# git rebase --abort
逆に、すでにpushして他の人が見ているブランチをrebaseするのは避ける。どうしても必要なら、通常の --force ではなく --force-with-lease を使い、チームで「誰がいつ使ってよいか」をルール化してください。初学者が一番避けるべきなのは、他人の作業が入ったリモートブランチへ何となくforce pushすることです。これは本当に揉めます。
迷ったら「mergeしておけば安全」と覚えておけば、まず事故りません。rebaseは履歴をきれいにする道具であって、共有された過去を書き換える道具ではない、と切り分けるのがコツです。
コミットの粒度をどう決めるか
ブランチの次に効くのが、コミットの粒度です。原則は1つ。1コミット=1つの意味にする。
ありがちな失敗が git add -A で全部まとめてコミットすること。便利ですが、一時ファイルや別作業の修正まで巻き込みます。基本は差分を見てから、必要なファイルだけstageします。
git diff --stat # まず全体の変更量を眺める
git add src/checkout/validateCoupon.ts
git add tests/checkout/validateCoupon.test.ts
git diff --staged --stat # これからコミットする中身を確認
git commit -m "feat(checkout): validate coupon expiry before payment"
メッセージは Conventional Commits 風(feat: fix: docs: など)にしておくと、後から履歴を検索しやすくなります。読者や顧客に影響する変更なら、理由を本文(body)に残します。
git commit -m "fix(content): keep Git workflow CTA localized" \
-m "翻訳ページと日本語の正本で同じ内部リンクとレビュー手順を踏むように本文を更新。"
粒度の目安はこんな感じです。
- 1つの振る舞いの変更+そのテスト → 1コミット
- リファクタと機能追加 → 必ず別コミット(混ぜると後で読めない)
- 大きな設計変更 → 「型・テスト追加」「内部実装の変更」「不要コード削除」に分ける
大きなリファクタを1コミットで終わらせないのが特に大事です。先に型やテストを足すコミット、次に実装を変えるコミット、最後に削除するコミット、と分けておくと、どこで壊れたかを git bisect で機械的に追えます。
PR運用:小さく出して、自分で説明する
チームなら、ブランチはPull Request(PR)で本流に合流させます。PRレビューで止まる一番の原因は、差分が大きすぎることです。
僕が意識しているのは「レビュアーが10分で読み切れる量」。目安として変更行数が数百行を超えたら、機能を分けてPRも分けます。差分が小さいほどレビューは速く、見落としも減る。PRの説明欄には「何を・なぜ・どう確認したか」を自分で書く。これだけでレビューの往復がぐっと減ります。差分サイズを機械でチェックする仕組みまで含めた具体的な型は、レビューで止まるPRを減らす型にまとめました。
PRを出す前に、ローカルで最低限のチェックを通しておくのも効きます。存在するnpm scriptだけ実行する小さなpreflightを置くと、プロジェクトをまたいで使い回せます。
# PR前のローカル確認:空白エラーと、あるチェックだけ回す
git diff --check # 余計な空白・コンフリクト跡を検出
npm run lint --if-present
npm run typecheck --if-present
npm test --if-present
「手元では動いた」をPRに持ち込まないだけで、本流が赤くなる回数が目に見えて減ります。
Claude Codeと併用するときのブランチ運用
ここが本題の応用編です。Claude Codeに実装を任せると、差分が一気に増えます。だからこそ、枝を切る前に範囲を固定するのが効きます。
僕の運用はこうです。slug(記事)や機能の単位で短命ブランチを切り、Claude Codeへの最初の依頼で「触ってよい場所」と「触ってはいけない場所」を先に宣言する。実装よりも範囲指定を優先するのがコツです。
下のスクリプトは、日付入りの短命ブランチを安全に作るところまでをまとめたものです。そのままコピペで動きます。
#!/usr/bin/env bash
# new-branch.sh — trunk-basedな短命ブランチを安全に切る
set -euo pipefail
topic="${1:?使い方: ./new-branch.sh <topic> 例) ./new-branch.sh coupon-validation}"
date_str="$(date +%Y%m%d)"
branch="feature/${date_str}-${topic}"
# 作業場に未コミットの変更が残っていたら、先に止める
if [ -n "$(git status --porcelain)" ]; then
echo "未コミットの変更があります。先に整理してください:"
git status --short
exit 1
fi
git fetch origin
git switch main
git pull --ff-only origin main # 本流を最新化してから枝を切る
git switch -c "$branch"
echo "ブランチを作成しました: $branch"
echo "Claude Codeへの最初の依頼に、触ってよい範囲と対象外を必ず書きましょう。"
Windows派なら、同じことをPowerShellでもできます。
# new-branch.ps1 — PowerShell版
param([Parameter(Mandatory=$true)][string]$Topic)
if (git status --porcelain) {
Write-Host "未コミットの変更があります。先に整理してください:"
git status --short
exit 1
}
$date = Get-Date -Format "yyyyMMdd"
$branch = "feature/$date-$Topic"
git fetch origin
git switch main
git pull --ff-only origin main
git switch -c $branch
Write-Host "ブランチを作成しました: $branch"
枝を切ったら、Claude Codeへの最初の依頼で範囲を縛ります。実装内容より先に、これを渡します。
Goal: クーポンの有効期限チェックをcheckoutに追加する。
Scope: src/checkout, src/coupons と対応するテストだけ編集する。
無関係なファイルのstage・commit・push・編集はしないこと。
編集前に package.json と既存のcheckoutテストを読むこと。
編集後は git diff --stat と、実際に実行したテストコマンドを示すこと。
この一文があるだけで、Claude Codeがついでに設定ファイルや別の記事まで直す事故が減ります。僕が記事更新で何度も失敗したのは、「記事本文だけ」と言ったつもりで、実際には画像選定スクリプトや商品ページまで同じ差分に混ざったケースでした。最初に対象外を明記すると、レビュー時間がはっきり短くなります。
繰り返しのルールは CLAUDE.md(Claude Codeが読むプロジェクト用の作業メモ)に固定しておくと、毎回入力せずに済みます。「git add -A は使わない」「コミット前に git diff --staged --stat を出す」「危険なGit操作は人間に確認する」あたりを書いておくと安定します。
僕がやらかしたブランチの失敗3つ
正直に書きます。戦略を整える前は、ブランチ周りで何度も転びました。
ひとつ目は、枝を長生きさせすぎたこと。「大きな機能だから」と2週間1本のブランチで作業したら、本流が先へ進みすぎて、最後のマージが地獄でした。コンフリクトが何十か所も出て、解くだけで半日。あれ以来、大きな機能も小さなコミットに割って、こまめに本流へ取り込むようにしています。
ふたつ目は、共有済みブランチをrebaseしたこと。履歴をきれいにしたくて、push済みの枝を rebase して --force でpushしたら、同僚の手元の履歴が壊れました。彼の作業が宙に浮いて、復旧に2人がかりで時間を使った。rebaseはpush前だけ、を体で覚えた瞬間です。
みっつ目は、コミットに意味を込めなかったこと。update fix だけのメッセージを並べていたら、半年後に「なぜこのファイルが変わったのか」を自分でも説明できませんでした。Claude Code作業だと差分が多い分、これが余計に効きます。差分の説明責任までコミットの一部だと考えるようになってから、過去の自分に助けられる回数が増えました。
よくある質問
Q. 個人開発でもブランチを切る意味はありますか?
A. あります。main 直コミットだと、実験が失敗したとき本流ごと汚れます。短命ブランチを切っておけば、ダメなら枝ごと削除して終わり。trunk-based で十分です。
Q. trunk-based と git-flow、結局どっちがいいですか?
A. 迷ったら trunk-based です。git-flow は複数バージョンを並行保守するプロダクト向け。Webサービスや個人開発では develop の二重管理が手間になりがちです。
Q. rebaseとmerge、どちらを使えばいいですか? A. push前のローカル掃除はrebase、共有ブランチの合流はmerge。迷ったらmergeにしておけば安全です。push済みのコミットをrebaseしてはいけない、がGit公式の鉄則です。
Q. コミットはどのくらい細かく分けるべきですか?
A. 「1コミット=1つの意味」が目安。機能追加とリファクタは必ず分けます。後で git bisect や git revert で1つずつ扱えるかを基準にすると判断しやすいです。
Q. Claude Codeが無関係なファイルまで変更してしまいます。
A. 枝を切る前に「触ってよい場所」と「対象外」を依頼文で明記し、CLAUDE.md に固定してください。git add -A を避け、git diff --stat で確認してから必要なファイルだけstageします。
実際に試した結果
ClaudeCodeLabの記事更新で、僕は trunk-based に寄せた運用へ全面的に切り替えました。slug単位で短命ブランチを切り、最初の依頼で対象外を宣言し、push前だけrebaseで整える。たったこれだけで、レビューは「全文を読み直す」から「対象slug・locale・差分の範囲を見る」へ絞れました。
特に効いたのは、枝を長生きさせないことと共有後はrebaseしないことの2つです。前者でマージ地獄が消え、後者で同僚との履歴トラブルがゼロになりました。Claude Codeの価値は速く書くことだけではなくて、戻せる単位を小さく保って、次の人が安全に進める状態を作れることにあると、今は思っています。
ブランチ戦略の次に効くのはコンフリクトの解き方です。同じ場所を別の変更が触ったときの落ち着いた直し方はClaude CodeでGitコンフリクトを安全に解決するに、PRをレビューで止めない型はレビューで止まるPRを減らす型にまとめました。手元の確認コマンドを一式そろえたいなら教材・テンプレート一覧もどうぞ。チームの分岐ルールごと設計したい場合はClaude Code研修・導入相談で、いまの開発フローを題材に組み立てられます。
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
まず無料PDFで基本を固め、繰り返し使う作業はGumroad教材へ、チーム導入や権限設計は導入相談へ進めます。
この記事を書いた人
Masa
Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
Claude Codeに1ファイルだけ直させる指示文のつくり方
「もっと良くして」で40行も変えられた失敗から学んだ、触る範囲・検証・戻し方をセットにしたClaude Code用の依頼文テンプレートを紹介します。
Claude Code の権限拒否から復旧する: 止まった理由を次の安全手順に変える
Claude Code のコマンドが拒否されたとき、焦って許可を広げずに、拒否理由、代替手順、証拠コマンド、再試行条件へ分解する方法。
Claude Codeにビルド→スモークテスト→自動修正を回させる足場の作り方
最小スモークテストの選び方、失敗ログを食わせて直させるループ、回数上限と確認ゲートで暴走を止める方法を、コピペで動くコード付きで紹介します。