web-dev-qa-db-ja.com

Gitマージdiff3スタイル説明が必要

2つのブランチをマージしましたが、競合が発生しました。開始点と終了点などのヒントが必要になります。読みやすく、話しやすくするために、コードを偽のデータに置き換えました。

<<<<<<< HEAD
    aaaaaa
||||||| merged common ancestors
<<<<<<< Temporary merge branch 1
    bbbbbb
=======
    cccccc
>>>>>>> mybranch
    dddddd
<<<<<<< HEAD
    eeeeee
||||||| merged common ancestors
    ffffff
||||||| merged common ancestors
    gggggg
=======
>>>>>>> Temporary merge branch 2
=======
    hhhhhh
>>>>>>> mybranch
33
mingle

この例(Temporary merge branchマーカー付き)に表示されているのは、交差マージの競合を伴うdiff3の結果です。これを一連の定義で説明します。

定義

  • マージベース:2つのマージブランチが最近分岐したコミット。マージの競合が発生すると、両方のブランチの同じ行に異なる変更が加えられました。 merge baseには、いずれかのブランチが変更する前の行が含まれています。
  • マージされた共通の祖先:diff3は、マージベースにあった行を示す追加の「中央」セクションを出力します。これが両方のブランチの開始点です。
  • Criss-cross merge:2つのブランチが、早送りマージではあり得なかった方法で互いにマージするマージ履歴。以下に例を示します。クロスクロスマージの状況では、複数のマージベースがあります。
  • 一時的なマージブランチ:複数のマージベースがある場合、diff3はそれらを(一時的なマージブランチを使用して)マージして形成しようとしますdiff3の中央セクションに表示される単一の共通の祖先。これは、競合がない場合はシームレスに機能しますが、競合がある場合は、中央のマージされた共通の祖先セクション内に一時的なマージブランチの競合マーカーが表示されます。

クロスマージ競合シナリオの例

クロスクロスマージは、2つのブランチが異なる時点で互いにマージするたびに発生します。

m3 *
   |\
   | \
   |  * B1
   |  |
m2 *  * B0
   |\/|
   |/\|
m1 *  * A
   | /
   |/
m0 *

次の一連のイベントについて考えてみます。

  • m0はOriginとして存在します/ m aster
  • 1つのコミットで機能ブランチfeature-Aを作成しますA
  • m1は他の誰かによってマスターにコミットされます
  • Aに基づいて構築された新しい機能ブランチfeature-Bを開始します
  • Origin/masterm1)をfeature-Bにマージします。競合し、解決します。マージコミットはB0です。
  • 機能Bを実装し、作業をB1としてコミットします。
  • feature-Aは出荷の準備ができているので、誰かがそれをmasterにマージします。競合します。彼らはそれを解決しますが、彼らの解決策はB0の解決策とは異なります。マージコミットはm2です。
  • feature-Bは出荷の準備ができているので、誰かがそれをmasterにマージします。 gitはマージベースを決定しようとしますが、m1Aはどちらもマージベースとして同等に適格です。 gitはm1A一時マージブランチでマージします。これにより、競合が発生します。 OPの質問と同様に、マージされた共通の祖先セクションにdiff3の出力が表示されます。

出力の読み取り

Diff3をオフにすると、このマージの競合は次のようになります。

<<<<<<< HEAD
    aaaaaa
=======
    hhhhhh
>>>>>>> mybranch

まず、すべての追加マーカーを使用して、実際の競合する行が何であるかを判別する必要があるため、diff3共通の祖先出力と区別することができます。

conflict with merged common ancestor blurred

aaaaaahhhhhh、それは少し良いです。 ;-)

2つの競合解決が競合している場合、aaaaaahhhhhhが2つの解決です。

次に、マージされた共通の祖先の内容を調べます。

merged common ancestor conflicts, grouped

この特定のマージ履歴では、2つ以上のマージベースがあり、複数の一時的なマージブランチが必要でした。マージベースが多く、競合がある場合の結果は、かなり毛深いものになり、読みにくくなる可能性があります。気にしないで、これらの状況ではdiff3をオフにするだけだと言う人もいます。

また、gitは内部的に異なるマージ戦略を使用して競合を自動解決することを決定する可能性があるため、出力を理解するのが難しい場合があることにも注意してください。可能であればそれを理解してください、しかしそれが人間の消費を意図していないことを知ってください。この場合、mybranchbbbbbbの間でccccccTemporary merge branch 1にマージするときに競合が発生しました。行ddddddには、一時的なマージブランチ間で競合はありませんでした。次に、Temporary merge branch 2HEADにマージするときに、複数の共通の祖先との別の競合が発生しました。 HEADffffffggggggeeeeeeとしてマージすることで競合を解決しましたが、Temporary merge branch 2は削除(または移動)することで同じ競合を解決しました行(したがって、======Temporary merge branch 2の間に行はありません。

このような競合をどのように解決しますか?テクニカル分析は可能かもしれませんが、通常、最も安全なオプションは、競合に関連するすべてのブランチの履歴に戻って確認し、理解に基づいて手動で解決策を作成することです。

これをすべて回避する

これらの競合は最悪ですが、それらを防ぐのに役立ついくつかの動作があります。

  1. 十字のマージは避けてください。上記の例では、feature-BOrigin/masterB0としてマージしました。マスターと最新の状態を保つためにこのマージが必要でなかった可能性があります(場合によっては必要ですが)。 Origin/masterfeature-Bにマージされなかった場合、マージの十字形はなく、m3は唯一のマージベースとしてのAとの通常の競合でした。 。

    m3 *              m3 *
       |\                |\
       | \               | \
       |  * B1           |  * B1
       |  |              |  |
    m2 *  * B0   VS   m2 *  |
       |\/|              |\ |
       |/\|              | \|
    m1 *  * A         m1 *  * A
       | /               | /
       |/                |/
    m0 *              m0 *
    
  2. 競合の解決と一致している。この例では、一時的なマージベースの競合は、m2B0の競合解決が異なるためにのみ発生しました。彼らが同じように競合を解決した場合、m3は完全なマージでした。ただし、これは単純な十字型のマージであり、同じ解像度である必要があることを認識してください。他の状況では、当然、解像度が異なる場合があります。マージベースが3つ以上あり、マージポイント間に複数のコミットがある場合、状況はさらに複雑になります。とは言うものの、交差する状況での紛争解決と故意に矛盾している場合は、後で頭痛がすることを期待してください。
41
Edward Anderson

gitのdiff3マージスタイル に関する記事があります。このスタイルで行が追加されているのか削除されているのかを判断するのは難しいと指摘しています。

特定の情報を探している場合は、質問を絞り込むことをお勧めします。あなたが何を求めているのか見分けるのは難しいです。

2
neontapir