異なるgitマージ戦略をいつ使用しますか?


430

git-mergeのmanページから、いくつかのマージ戦略を使用できます。

  • resolve -3ウェイマージアルゴリズムを使用して解決できるのは、2つのヘッド(つまり、現在のブランチとプルした別のブランチ)だけです。それは交差交差のあいまいさを注意深く検出することを試み、一般に安全かつ高速であると考えられています。

  • 再帰的 -これは、3方向マージアルゴリズムを使用して2つのヘッドのみを解決できます。3ウェイマージに使用できる共通の祖先が複数ある場合は、共通の祖先のマージされたツリーを作成し、それを3ウェイマージの参照ツリーとして使用します。これにより、Linux 2.6カーネル開発履歴から取得された実際のマージコミットに対して行われたテストで、マージのミスを引き起こさずにマージの競合が減少すると報告されています。さらに、名前の変更を伴うマージを検出して処理できます。これは、1つのブランチをプルまたはマージするときのデフォルトのマージ戦略です。

  • タコ -これは2頭以上のケースを解決しますが、手動での解決が必要な複雑なマージを拒否します。これは主に、トピックのブランチヘッドをまとめるために使用することを目的としています。これは、複数のブランチをプルまたはマージするときのデフォルトのマージ戦略です。

  • 私たち -これは任意の数のヘッドを解決しますが、マージの結果は常に現在のブランチヘッドになります。これは、サイドブランチの古い開発履歴に取って代わるために使用されることを意図しています。

  • サブツリー -これは修正された再帰戦略です。ツリーAとBをマージするとき、BがAのサブツリーに対応する場合、Bは、同じレベルでツリーを読み取るのではなく、最初にAのツリー構造に一致するように調整されます。この調整は、共通の祖先ツリーに対しても行われます。

デフォルトとは異なるものをいつ指定する必要がありますか?それぞれに最適なシナリオは何ですか?

回答:


305

私はresolveについては詳しくありませんが、他のものを使用しました:

再帰的

再帰は、非早送りマージのデフォルトです。私たちは皆、それをよく知っています。

たこ

マージする必要のあるいくつかのツリーがあるとき、私はタコを使用しました。これは、多くのブランチが独立した開発を行っており、すべてをまとめて1つのヘッドにする準備ができている、より大きなプロジェクトで見られます。

タコのブランチは、きれいにできる限り、1つのコミットで複数のヘッドをマージします。

例として、マスターがあり、マージする3つのブランチ(a、b、cと呼ぶ)があるプロジェクトがあるとします。

一連の再帰的マージは次のようになります(最初のマージは再帰を強制しなかったため、早送りであったことに注意してください)。

一連の再帰的マージ

ただし、1つのタコのマージは次のようになります。

commit ae632e99ba0ccd0e9e06d09e8647659220d043b9
Merge: f51262e... c9ce629... aa0f25d...

タコのマージ

私たちのもの

私たちの==私は別の頭を引き出したいのですが、頭がもたらすすべての変更を捨てます。

これにより、ブランチの影響なしにブランチの履歴が保持されます。

(読み取り:これらのブランチ間の変更も調べられません。ブランチはマージされ、ファイルには何も行われません。他のブランチにマージしたい場合、「ファイルバージョンまたはバージョン」を使用できますgit merge -X ours

サブツリー

サブツリーは、別のプロジェクトを現在のプロジェクトのサブディレクトリにマージする場合に役立ちます。サブモジュールとして含めたくないライブラリがある場合に役立ちます。


1
それで、Ocotopusの唯一の本当の利点は、ツリーのマージコミットの数を減らすことです?
Otto

60
タコのマージ戦略を指定する必要はありません。3つ以上のブランチをマージする場合は自動的に使用されます(git merge A B ...)。
JakubNarębski、2009

話題から外れて申し訳ありませんが、それらのスクリーンショットを作成したツールは何ですか?ブランチの履歴を視覚的に表現するのに非常に優れています
Bernd Haug

4
Linux環境のユーザー向けのgitg
Akash Agrawal 14

2
このヒント-X oursは素晴らしく、1時間の作業を節約してくれました。
マイケル

49

実際にあなたが選択したいと思う唯一の2つの戦略がある私たちは、あなたが枝によってもたらされた変化を放棄するが、歴史の中で枝を維持したい場合、およびサブツリーあなたは「gitの-guiの」 'のように(親プロジェクトのサブディレクトリに独立したプロジェクトをマージしている場合git 'リポジトリ)。

タコのマージは、3つ以上のブランチをマージするときに自動的に使用されます。 resolveは主に歴史的な理由と、再帰的なマージ戦略のコーナーケースに遭遇した場合のためにここにあります。


致命的なgit-write-treeエラーが発生した2ヘッドマージでは、デフォルトの「再帰的」ではなく「解決」を選択する必要がありました。「解決」戦略は完全に統合されました。マージされるブランチ内で多くのファイルを移動する必要があったかもしれません。
thaddeusmt 2012年

@thaddeusmt:興味深い。可能であれば、この「再帰的」マージ戦略の失敗に関するバグレポートをgitメーリングリストに投稿してください。前もって感謝します。
JakubNarębski12年

@JakubNarębski意味のあるバグ報告を提出するのに十分な情報をどのように収集できるかわかりません。私はGitのn00bです。申し訳ありません。ここでの回答(stackoverflow.com/a/10636464/164439)で述べたように、私の推測では、両方のブランチで変更を複製する必要があり、 "resolve"は複製された変更をスキップするというより優れた仕事をします。
thaddeusmt

@JakubNarębski では、手動で「彼らのもの」を選択することもできます。これは、「私たちのものの反対です。彼らのものは自動的には選択されません。あなたのアンサーを少し更新して、彼らのオプションを追加できます
SebNag

3
@SebTu:theirsマージ戦略(つまり--strategy=theirs)はありませんがtheirs、デフォルトのrecursiveマージ戦略(つまり--strategy=recursive --strategy-option=theirs、または単に-Xtheirs)にはオプションがあります。
JakubNarębski、2017

23

「解決」対「再帰」マージ戦略

再帰は現在のデフォルトの2ヘッド戦略ですが、検索を行った後、ようやく「解決」マージ戦略に関する情報を見つけました。

O'Reillyの書籍「Version Control with GitAmazon)」から抜粋(言い換え):

当初、「解決」はGitマージのデフォルトの戦略でした。

可能性のあるマージ基準が2つ以上あるような、クロスクロスマージの状況では、解決戦略は次のように機能します。考えられるマージベースの1つを選択し、最良のものを期待します。これは実際には思ったほど悪くはありません。多くの場合、ユーザーがコードのさまざまな部分で作業していることがわかります。その場合、Gitは既に行われている変更を再マージしていることを検出し、重複を回避して競合を回避します。または、これらが競合の原因となるわずかな変更である場合、少なくとも競合は開発者が処理しやすいはずです。

デフォルトの再帰戦略で失敗した「解決」を使用してツリーを正常にマージしました。fatal: git write-tree failed to write a treeエラーが発生しました。このブログ投稿ミラー)のおかげで、「-s resolve」を試してみましたが、うまくいきました。理由はまだ正確にはわかりませんが、両方のツリーで重複した変更があり、それらを適切に「スキップ」して解決したためだと思います。


私は3方向マージ(p4merge)を使用しており、再帰的マージが失敗したときに.BASEファイルに競合が書き込まれました。この場合は、解決戦略にフォールバックすることが役立ちました。
mrzl 2012


-2

上記の回答はすべての戦略の詳細を示しているわけではありません。例えば、いくつかの答えは、インポートの詳細は不足しているresolveオプションをし、recursive多くのサブオプションを持っているとしてourstheirspatiencerenormalize、など

したがって、gitすべての可能な機能の機能を説明している公式ドキュメントにアクセスすることをお勧めします。

https://git-scm.com/docs/merge-strategies

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.