moreTweetgitのコンフリクト(衝突)について調べてみました。前置きとかもういいよね。ちなみにこの記事ではrerereについては述べませんし、使われていない前提で書かれています(よくわかんないしね!)備考この記事の操作は手元で再現することができます。(Gitクライアントがインストールされてることが前提です。各操作毎にブランチを分けているのでチェックアウトして使ってください。気軽にStarつけてね!どのようなコミットグラフになっているかはGithubで見るか、クローンしてGUIクライアントで見るなりしてください。)3ウェイマージは、ファイル'A'と'B'の差分、およびそれらの親にあたるファイル'C'(多くの場合、ファイル'A'と'B'は共通の親を持つ)との差分の分析結果を元に行われる。バージョン管理システムでは親にあたるファイルが必ず存在し、またどのファイルが親かもはっきりしているため、3ウェイマージの使用に適している。マージ用ツールは各ファイル間の差分およびその中に現れるパターンを調査し、マージを行うためにファイル'A','B','C'の間の関係モデルを生成した上で、新しいリビジョン’D'を作り出す。結論から言うとgitのデフォルトのマージアルゴリズムだと共通祖先との差分範囲が重なっており、重なった差分が異なる場合にコンフリクトとなるようです。いうことで以下のパターンにおいて、それぞれの「共通祖先との差分」と「マージ結果」をみていきましょう。いうブランチを使います。diffも共通祖先リビジョンで行っています。マージに失敗するパターンから。fail4-fromdiffの「/」(スラッシュ)左の「a」やら「b」はファイル名とは関係なく差分(diff)対象の区別です。右側はファイル名です。続いてマージに成功するパターンです。aa1a2空行(パターン2)だったら優先されるとか、前方一致(パターン3)なら補完してくれるとかそんな幻想をぶち壊されますね。引っかかるのは片方の差分で行が多いだけ(パターン4)ならマージできそうだと思ってしまいそうなところです。行末の改行コードの有無とかでぶつかっちゃうのかな。知ってる人は教えてください。これによって何が変わるかを以下の例でみていきましょう。「a2」もしくは「A2」という行をもつコミットに統合を試みた時の「マージ」と「リベース」の成功・失敗を比較しています。「マージ先と共通祖先の差分」と「マージ元と共通祖先の差分」のみを比較します。片方のみで変更された場合でもコンフリクトとなります。書きましたが、リベースは差分を一つ一つ比較していきます。途中まで同じ差分を持っていて、その後片方のみで変更が行われた場合、リベースではコンフリクトとはなりません。逆に最後で帳尻を合わせ同じ差分としても途中で異なる差分がある場合はコンフリクトとなります。個人的にリベースのほうが少し人間的に感じますが、どちらも一長一短があるということです。ここでリベースのコンフリクト解決順について少し実験をしてみましょう。リベースしてみましょう。この2つのブランチは「conflict-test」ブランチを基点として以下のような手順で作られます。README上記の操作から以下がわかります。コンフリクトの解消はリベース元ブランチのリビジョン単位で行われるコンフリクトの解消でリベース元差分を選択しなくてもログには残る。ログに残さないためにはskipする。リビジョンも古い順に一つずつ比較されていくようです。マージツール使ったコンフリクトの解消はいつか。