web-dev-qa-db-ja.com

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

Git-mergeのmanページから、使用できる多くのマージ戦略があります。

  • resolve-これは、3方向マージアルゴリズムを使用して2つのヘッド(つまり、現在のブランチと別のブランチ)のみを解決できます。これは、十字のマージのあいまいさを注意深く検出しようとするものであり、一般に安全かつ高速であると考えられています。

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

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

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

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

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

409
Otto

私は解決に精通していませんが、他のものを使用しました:

再帰的

再帰は、非早送りマージのデフォルトです。私たちは皆、これに精通しています。

たこ

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

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

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

一連の再帰的なマージは次のようになります(再帰を強制しなかったため、最初のマージは早送りでした)。

series of recursive merges

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

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

octopus merge

私たちのもの

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

これにより、ブランチの影響を受けずにブランチの履歴が保持されます。

(読んでください:それらのブランチ間の変更も見ていません。ブランチは単にマージされ、ファイルには何も行われません。バージョン」を使用できますgit merge -X ours

サブツリー

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

296
Dustin

実際に選択したいのは、ブランチによってもたらされた変更を破棄し、ブランチを履歴に残したい場合はours、そして独立してマージしている場合はsubtreeのみです。スーパープロジェクトのサブディレクトリにプロジェクトを作成します(「git」リポジトリの「git-gui」など)。

octopusmergeは、3つ以上のブランチをマージするときに自動的に使用されます。 resolveは、主に歴史的な理由、およびrecursive戦略コーナーケースをマージします。

46
Jakub Narębski

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

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

O'Reillyの本から引用 Gitによるバージョン管理Amazon )(言い換え):

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

複数の可能なマージベースがある十字型マージの状況では、解決戦略は次のように機能します。可能なマージベースの1つを選択し、最適な結果を期待します。これは実際には思ったほど悪くありません。ユーザーがコードのさまざまな部分で作業していることがしばしばわかります。その場合、Gitは既に配置されている一部の変更を再マージしていることを検出し、重複する変更をスキップして、競合を回避します。または、これらが競合を引き起こすわずかな変更である場合、少なくとも競合は開発者が処理しやすいはずです。

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

21
thaddeusmt