5

これはおそらく長い質問になると思いますので、ご容赦ください。

ここで、git マージの決定に関する信じられないほどの説明に出くわしました: How does git merge work。私はこの説明に基づいて構築しようとしており、このように git merge を描写することに穴があるかどうかを確認しています。基本的に、マージされたファイルに行が表示されるかどうかの決定は、真理値表で表すことができます。

W: 元のファイル、A: Alice のブランチ、B: Bob のブランチ

真理値表

この真理値表に基づいて、D を構築するための行ベースのアルゴリズムを考えるのは簡単です。 A と B から対応する行を見て、真理値表に基づいて決定を下すことにより、D を行ごとに構築します。

私の最初の質問はケース (0, 0, 1) で、上に投稿したリンクによると、そのケースは実際には競合していますが、git は通常、とにかく行を削除することでそれを処理することを示唆しているようです。この場合、実際に紛争につながる可能性はありますか?

2 番目の質問は、削除のケース (0, 1, 1) と (1, 0, 1) についてです。直観的には、これらのケースの処理方法が問題につながる可能性があると感じています。W に関数 foo() があったとしましょう。この関数は実際にはどのコードでも呼び出されませんでした。ブランチ A で、アリスが最終的に foo() を削除することを決定したとしましょう。しかし、分岐 B で、ボブは最終的に foo() の使用を決定し、foo() を呼び出す別の関数 bar() を作成しました。直感的に、真理値表に基づいて、マージされたファイルは foo() 関数を削除し、bar() を追加することになり、Bob はなぜ foo() が機能しなくなったのか不思議に思うでしょう! おそらく、私が 3 通りのマージのために導き出した真理値表モデルは、おそらく完全ではなく、何かが欠けていると思いますか?

4

2 に答える 2

5

私の最初の質問はケースです (0, 0, 1)

darcs のような一部のバージョン管理システムは、2 つのブランチで同じ変更 (あなたの場合は削除) を行い、それらをマージすると競合が発生するはずだと考えています。典型的な例は、あなたが2回持っているときです

-#define NUMBER_OF_WHATEVER 42
+#define NUMBER_OF_WHATEVER 43

マージ アルゴリズムは、マージで 43 (これは両方のバージョンが同意する値であるため) または 44 (42 は 2 回インクリメントする必要があるため) を生成するかどうかを知ることができません。

ただし、このケースを競合と見なすと、多くの偽の競合が発生します。たとえば、マスター ブランチからメンテナンス ブランチへのマージをチェリー ピックし、後でメンテナンス ブランチをマスターにマージすると、チェリー ピックによって変更された各行が競合につながります。そして、競合マーカーは、次のように、競合マーカーの両側に同じコンテンツを表示するため、奇妙になります。

<<<<<<< HEAD
Hello world
=======
Hello world
>>>>>>> 77976da35a11db4580b80ae27e8d65caf5208086

そのため、Git を含むほとんどのバージョン管理システムは、マージの両側で同じ変更が導入された場合、競合がないと見なすことを選択しました。

2 番目の質問は、削除のケース (0, 1, 1) と (1, 0, 1) についてです。

あなたが説明しているのはセマンティックな競合です。それらは理論的には存在し、マージがコンパイル可能であるが、マージされるブランチと比較してセマンティクスが異なるコーナーケースを見つけることさえできます。魔法のようなものはありません。セマンティックの競合を検出または解決できるテキスト マージ アルゴリズムはありません。あなたは彼らと一緒に暮らすか、一人で働かなければなりません。

実際には、それらは十分にまれです。おそらく何百万人もの人々がバージョン管理システムを毎日使用し、それとともに生活しています。大多数は、おそらく問題が存在するとは考えていませんでした。

それでも、優れた組織は、セマンティック コンフリクトのリスクを大幅に減らします。マージ後もコードがコンパイルされることを確認すると、セマンティック コンフリクトの最大 90% を回避できます。また、自動テスト スイートを使用している場合は、セマンティック コンフリクトを見つけて、テスト スイートでカバーされていないバグを作成する必要があります。問題になる。

実際、セマンティック コンフリクトはバージョン管理システムに固有のものではありません。マージを使用しない別のシナリオは

  • コードを読むと関数が表示されますf()
  • 同僚が機能を削除しますf()
  • 今はもうない最新版に取り組んでいるのf()ですが、今でも機能があることを思い出してf()使ってみています。

要するに、セマンティックの競合を恐れないでください。

于 2015-05-23T08:16:17.263 に答える
2

さまざまなマージ動作を自分でテストするためのサンプル リポジトリを次に示します。互いにマージするためのさまざまな変更を加えたたくさんのブランチがあります。

自由にフォークまたはクローンしてください。

git clone https://github.com/NickVolynkin/GitMergeResearch.git

すぐに結果を投稿します。

ここに画像の説明を入力

于 2015-05-23T12:18:38.803 に答える