私は git を初めて使用します。早送りマージとは何かを理解しています [2 つの分岐が線形の場合は、ポインタを分岐に移動するだけです]。新しいコミットを作成するには、なぜ2つのブランチ[マージしたいブランチ(例:マスター)とマージしたいブランチ(例:immediatefix)]を取ることができず、それらを比較してマージを行うだけです..なぜそうするのですか共通の祖先が必要です。また、共通の祖先が必要な理由をリベースします...
1 に答える
それはかなり単純で、Git ストアがコミットする方法に要約されます。他の VCS とは異なり、Git は作業ディレクトリ全体の完全なスナップショットを保存します。そのため、単一のコミットを見ると、そのコミットの内容の正確な状態しかわかりません。
Subversion のような他の VCS は通常、差分を保存します。そのため、リビジョンは以前の状態と現在の状態の違いとして保存されます。したがって、マージするときは、単一のリビジョンを調べて何が起こったかを確認するだけでよく、それを別の場所に適用できます。
一方、Git にはその違いがすぐに利用できるわけではありません。コミットで何が起こったかを確認するには、内容を親コミットと比較する必要があります。そうして初めて、違いを生み出し、それを別の場所に適用することができます。したがって、2 つのブランチA
とB
共通のベースがある場合、Git が行うことは、と、 とのC
違いを調べることです。次に、各ブランチで何が起こったかを正確に把握し、すべての変更を適用しようとすることができます。これにはさらに、変更の全範囲が見られるという利点があります。そのため、あるブランチで何かを一時的に変更し、後で元に戻した場合、マージ時に完全な違いが表示されません。これにより、通常、競合が少なくなります。A
C
B
C
同じことがリベースにも当てはまりますが、実際にはその名前になっています。にリベースB
するときA
は、基本的に範囲からのすべてのコミットを書き直して、代わりに親としてC..B
持つようにします。A
そのため、Git は とC
ブランチの最初のコミットの違いを調べ、それを に適用しますA
。次に、最初のコミットと 2 番目のコミットの違いを見て、それを適用します。そして、それはブランチ全体がリベースされてベースA
として持つようになるまで続きます。
ここで、A に完全なスナップショットがあり、B に完全なスナップショットがある場合、A と B を比較してマージできる場合、なぜ共通のベース C が必要なのか混乱します。
さて、これについて例を試してみましょう。簡単にするために 1 つのファイルだけを見ていきますが、これはリポジトリ内のすべてのファイルで発生します。
これがブランチ A のファイルの内容であるとします。
alpha
beta
gamma
そして、これはブランチ B のコンテンツです。
alpha
gamma
delta
マージされたバージョンはどのようなものになるでしょうか。コミットが実際に何を変更したのかわからない場合、それを安全に決定することはできません。たとえば、ファイルには元々 (C で) と のみが含まれていたと言えalpha
ますgamma
。そのため、ブランチ Abeta
に追加され、Bdelta
に追加されました。これにより、次のようになります。
alpha
beta
gamma
delta
または、ファイルには元々 4 行すべてが含まれていたので、Adelta
が削除され、Bbeta
が削除されたという逆を想定することもできます。
alpha
gamma
または、ブランチ B は実際にはファイルに触れていないため、その状態は無視され、A のコンテンツは保持されるべきであると言えます。ブランチ A がファイルに触れていない場合、同じことが逆に適用される可能性があります。
ご覧のとおり、これらのブランチのベースを持っているため、ブランチの実際の違いは、マージを解決する方法を決定するのに大いに役立ちます。結局のところ、ブランチを使用して他のブランチから独立して (他の独立した開発ラインを使用して) 開発し、マージ中にすべての作業を再度実行することなく、すべての変更をマージするだけです。