コンテンツへスキップ

Git Merge vs Rebase

どちらをいつ使うべきか、そしてなぜか――よくある疑問にFAQ形式で答えます。

Git Merge vs Rebase

開発者の間でよくある議論があります。チームがGitをどう使えば、全員が常にmainブランチの最新の変更に追いつけるのか、というものです。この疑問が生まれる典型的な状況は、誰かが新しいブランチで作業を行い、作業が完了してマージする準備ができた時に、mainブランチにその間に変更が入っていて、作業ブランチが古くなりマージコンフリクトが発生するケースです。

当然、作業ブランチをマージする前にコンフリクトを解決する必要があります。しかし問題は、この状況を「どう」解決すべきかということです。mainブランチを作業ブランチにmergeすべきでしょうか?それとも作業ブランチを最新のmainブランチにrebaseすべきでしょうか?

私の意見では、この質問には唯一の正しい答えがあります。経験上、このトピックについてこれほど多くの議論が生まれる主な理由は、このコンテキストにおけるmergeとrebaseの違いについて多くの誤解があり、そもそもrebaseとは何かについての理解が不足していることにあります。

そこで、チーム向けにこの点を明確にするFAQを作成しました。共有させてください。

mergeとは何ですか?

別のブランチのすべての変更を現在のブランチに統合するコミットです。

rebaseとは何ですか?

現在のブランチのすべてのコミットを、別のベースコミットの上に再コミットすることです。

mergeとrebaseの主な違いは何ですか?

  1. merge1つの新しいコミットだけを実行します。rebaseは通常複数のコミットを実行します(現在のブランチのコミット数分)。

  2. merge新しい生成されたコミット(いわゆるマージコミット)を作成します。rebase既存のコミットを移動するだけです。

どのような状況でmergeを使うべきですか?

分岐したブランチの変更をベースブランチに戻すときにmergeを使います。

通常、これはGitHubなどのPull/Merge Requestで「Merge」ボタンをクリックすることで行います。

どのような状況でrebaseを使うべきですか?

ベースブランチの変更を分岐したブランチに取り込みたいときにrebaseを使います。

通常、これはmainブランチに変更があったときにworkブランチで行います。

なぜベースブランチからの変更を作業ブランチにmergeするのは良くないのですか?

  1. Git履歴に多くの不要なマージコミットが含まれるようになります。作業ブランチで複数回のmergeが必要になった場合、実際のコミットよりもマージコミットの方が多くなることすらあります!

  2. Gitが設計された際のメンタルモデルを壊すループが作られ、Git履歴のどの可視化においても問題を引き起こします。

川(例えば「ナイル川」)を想像してください。水は一方向に流れています(Git履歴における時間の方向)。時々、川から分岐が生まれ、その分岐のほとんどは川に合流して戻ります。これが川の流れとして自然に見えるでしょう。理にかなっています。

しかし、その川に小さな支流があるとします。そして何らかの理由で、川が支流に合流し、支流がそこから続くとします。川は技術的には消滅し、今や支流の中にあります。しかし、なぜか魔法のように、その支流が川に合流して戻ります。どの川にかって?わかりません。川は本来もう支流の中にあるはずなのに、なぜかまだ存在し続けていて、支流を川に合流させることができます。つまり、川が川の中にある。意味が通りませんよね。

これはまさに、ベースブランチをworkブランチにmergeし、workブランチの作業が完了したらそれをベースブランチにマージし直すときに起こることです。メンタルモデルが壊れます。そのため、ブランチの可視化があまり役に立たなくなります。

merge使用時のGit履歴の例:

merge使用時のGit履歴の例

merge使用時のGit履歴の例

Merge branch 'main' into ...で始まる多くのコミット(黄色の四角でマーク)に注目してください。rebaseではこれらは存在しません(あるのはPull Requestのマージコミットだけです)。また、多くの視覚的なブランチマージループ(mainからworkへ、workからmainへ)にも注目してください。

rebase使用時のGit履歴の例:

rebase使用時のGit履歴の例

rebase使用時のGit履歴の例

マージコミットが大幅に少なく、煩雑な視覚的ブランチマージループが一切ない、ずっとクリーンなGit履歴です。

rebaseにデメリットや注意点はありますか?

あります。

  1. rebaseはコミットを移動する(技術的には再実行する)ため、移動されたすべてのコミットのコミット日時がrebase時点の日時になり、Git履歴は最初のコミット日時を失います。そのため、コミットの正確な日付が何らかの理由で必要な場合は、mergeの方が良い選択です。ただし、通常はクリーンなGit履歴の方が正確なコミット日時よりもはるかに有用です。

  2. rebaseされたブランチに同じ行を変更するコミットが複数あり、その行がベースブランチでも変更されている場合、同じ行のマージコンフリクトを複数回解決する必要がある場合があります。mergeではこの問題は起きません。つまり、平均的にはrebaseの方が解決すべきマージコンフリクトが多くなります。

rebase使用時にマージコンフリクトを減らすためのヒント:

  1. 頻繁にrebaseする。少なくとも1日1回行うことをお勧めします。

  2. 同じ行への変更はできるだけ1つのコミットにsquashするようにしましょう。

このFAQがどこかのチームのお役に立てば幸いです。

この記事が参考になりましたか?BlueskyMastodonでフォローして、Swiftのヒントやインディー開発の最新情報をチェックしてください。