ウェブサイト検索

Gitリベースとは何ですか?そして、それはマージとどう違うのですか?


マージとリベースは似たような目的を達成しますが、方法は異なります。どちらもブランチを管理し、複数の人と共同作業を行うのに役立ちますが、互換性があるわけではなく、適切に行わないとリベースは有害になることがあります。

リベースについての問題は何ですか?

リベースは非常に複雑なので、どのように機能するかを理解することが重要です。

git

私たちがそれを理解するために、内部で機能しています。

Gitはあなたのコードを一連の編集として保存します。これを鎖のように思うことができますが、逆方向に作動します。各編集、または「コミット」は、前のコミットのIDを参照し、前のコミットから何が変わったのかを含んでいます。この鎖はあなたのコンピュータにのみ保存されており、Gitクライアントは、別のGitクライアントと通信することはありません。

fetch

または

push

 (

pull

ほんとにただの

fetch + merge

あなたのローカルブランチと共に、しかしそれでも、共有リモートリポジトリと話しているだけです。

ブランチはより複雑です。Gitはブランチを扱うときに一つのことだけを保存します:ブランチの最後にあるコミットのIDです。このように考えると、ブランチはレコードプレーヤーの再生ヘッドのようなものです。ブランチヘッドを特定の位置に置くと、それがチェーンを遡り、「演奏」しながらコードにアクセスし、最終バージョンに到達します。コミットするたびに、ローカルのgitクライアントは自動的に再生ヘッドを新しいコミットに進めます。

機能をマスターにマージしたい場合は、次のように実行します:

git checkout master

git merge feature

これにより新しいマージコミットが作成され、もしコンフリクトがあれば、手動で解決する必要があります。git merge コマンドはマスタープレーヘッドを新しいマージコミットに移動し、もはや必要ないためフィーチャープレーヘッドを削除します。

このコードをマージする方法には3つの問題があります。

  • 機能ブランチが取り入れたいマスターブランチの変更があるかもしれません。特に、機能の開発に時間がかかっている場合はなおさらです。
  • ブランチで作業するたびにマージプロセスを強いられるのは面倒です。
  • コミット履歴は混乱していますが、これは主に美的な問題です。

リベースはこれらの問題を解決しようとしますが、成功の度合いは様々です。リベースはブランチの開始位置を変更します。全体のブランチが持ち上げられ、現在のマスターブランチの最後に運ばれ、つながります。マスターブランチはそのまま残され、コミットを受け取り続けることができます。

コミットは実際には移動しませんが、コミットは不変であるためです。むしろ、コピーされるため、新しいコミットIDが生成されます。以前のコミットは取り残され、あなたのGitファイルの中に隠れていて二度と見ることはありません。なぜなら、プレイヘッドは別の場所に移動してしまったからです。

このプロセスをコマンドラインから実行するには、次のように入力します:

git checkout feature

git pull

git rebase master

これによりブランチが開き、現在の変更がマスターに取り込まれ、その後フィーチャーブランチがマスターブランチにリベースされます。

この時点で、フィーチャーブランチのコードはより最新のものであり、これがgit rebaseの唯一の実際の機能です。リベースはブランチをマージしません。なぜなら、マージコミットを作成せず、masterのプレイヘッドも移動しないからです。

リベースの後にマージしたい場合は、次のように実行します:

git checkout master

git merge feature

これは、このように見えるでしょう。マスターの再生位置がフィーチャーの再生位置に置き換わります。

したがって、リベースはマージの処理に関する問題を解決することにはならず、結局マスターブランチを更新するために最終的にマージする必要があります。最終的なmergeコマンドは問題なく実行されるはずですが、リベースのプロセスでは変更を「マージ」する必要があり、これにより競合が発生する可能性があります。そして、もしブランチで作業を続けたい場合は、変更を「マージ」する必要があります。

共有ブランチをリベースしないでください

リベースがコミットをコピーし、孤立したプレイヘッドを残すことを思い出してください。それは共有コードで作業している場合、実際には大きな問題です。あなたが機能ブランチを作成し、同僚がテストできるようにそれをリポジトリにプッシュしたとしましょう。それはまったく問題ありませんが、彼らのうちの誰かがあなたのブランチから分岐したい場合、最終的にリベースをすると、こんなことになります:

あなたの同僚のfeature2ブランチは、現在古いコミットのチェーンを参照しています。あなたのGitクライアントにはこれを知る方法がありません。なぜならfeature2ブランチはあなたの同僚のコンピュータに保存されているからです。彼らも、あなたがリベースしたことをプッシュするまで知る手段がありません。

リベースしたとき、すべてのコミットをコピーする際に feature2 ブランチはコピーされませんでした。仮にできたとしても、それは同僚のローカル Git リポジトリに影響を与え、すべてが同期しなくなります。ここでの解決策は、feature2 を適切な位置にある feature にリベースすることですが、それは Git の基準でもかなり厄介です。これはただの非常にシンプルな例です。

結論として、ローカルで作業していない場合はリベースしないでください。

リベースはマージよりもいつ優れているのでしょうか?

もしあなたのブランチの開発に時間がかかる場合、リベースは「ブランチ症候群」の問題を解決します。これは、あなたのコードが作業中のマスターと非常に古くなってしまっており、作業を続けるために更新する必要がある状況です。一般的に言えば、この問題をできるだけ避けるべきですが、リベースは問題が発生したときにそれを修正できます。

もしあなたが小さな、徐々に増加する日々の変更を行っているだけなら、代わりにローカルのマスターブランチで作業し、変更をプッシュする準備ができたときにプルリクエストを使用すべきです。これらは、マージの承認が得られる前にコードを保存するために特に作成されたトピックブランチのモデルを使用します。

しかし、もしあなたが週単位で作業をしていて、複数のプルリクエストを作成し、何度もマージすることになるのであれば、少し長くコードに取り組み、更新のためにローカルでリベースし、一回のプルリクエストを最後に行うことで、テストや上司との話し合いの回数を減らすことができます。リベースは主にローカルで行うものであるため、承認を待つことなく、ステージングブランチで実施することができます。

もし他の誰もあなたのブランチに依存していなければ、ブランチのマージの前にリベースしてコミット履歴をクリーンで一元的にすることができます。しかし、伝統的なマージは確かに見栄えが悪いものの、マージコミットは完全に非破壊的であるため、追跡やデバッグが容易だという意見もあるでしょう。いずれにせよ、リベースは変更がマージされる直前に行う必要があります。さもなければ、あなたの変更が承認される前にマスターが更新されるという問題に直面する可能性があります。

関連記事: