終わらない聖戦:git merge vs git rebase
開発チームに新しいメンバーが2人入った月、その「聖戦」は始まりました。
Aさん(Rebase過激派):
「マージコミットなんて履歴がグチャグチャになるだけだ。rebase して履歴を一直線(直線的)にすべきだ!コミットツリーが電車の路線図みたいに分岐してるのを見ると吐き気がする!」
Bさん(Merge保守派):
「rebase は歴史の改ざんだ!『いつ、誰が、どのブランチを統合したか』という事実を消し去る悪魔のコマンドだ。コンフリクトの解消も面倒だし、素直に merge すべきだ!」
Slackの #engineering チャンネルは炎上。互いの正義がぶつかり合い、PRのレビューはGitの運用論争で埋め尽くされました。
それぞれの言い分は「どちらも正しい」
冷静に分析してみましょう。
Rebase派の正義(綺麗さ):
履歴が1本の線になるため、「どのコミットでバグが混入したか」を git bisect 等で探すのが非常に簡単になります。あと、見た目がシンプルで美しい。
Merge派の正義(真実):
「機能Aの開発ブランチが、ここでMasterに統合された」という**文脈(コンテキスト)**がコミットノードとして永遠に残ります。歴史をありのままに保存します。
チームが出した「究極の結論」
3時間のミーティングの末、私たちは「どちらか一方を選ぶこと自体が間違っていた」という結論に達しました。
そして、以下のハイブリッドなルールを制定しました。
ルール1:ローカルブランチの更新は rebase
自分の作業ブランチ(feature/login)を作った後、本流(main)に他人の更新が入ったとします。
この時、本流の変更を自分のブランチに取り込むのは rebase を使います。(git pull --rebase origin main)
これにより、無駄な「Merge branch 'main' into feature」というノイズコミットを防ぎます。
ルール2:本流(main)への統合は Squash and Merge または Merge --no-ff
作業ブランチを main に合流させる時は、rebase は絶対に使いません。
-
細かいコミットが多い場合:GitHubの「Squash and Merge」を使い、PRの変更を1つの綺麗なコミットにまとめて
mainに入れます。 - コミット履歴を残したい大きな機能:普通にマージ(マージコミットを作成)し、「このPRの塊がここで入った」という文脈を残します。
まとめ:個人空間は綺麗に、共有空間は真実を
-
ローカル(個人の作業場):他人の目を気にして、
rebaseで綺麗に化粧をする。 -
本流(チームの共有財産):何が統合されたかの「歴史の事実」を
mergeで残す。
このルールにしてから、Rebase過激派もMerge保守派も満足し、チームに平和が訪れました。Gitの運用に「唯一の絶対解」はありません。しかし、「個人の作業」と「チームの統合」を切り分けて考えると、争いの9割は消滅します。