나도 관심이 있습니다. 답은 모르겠지만 ...
작동하는 복잡한 시스템은 작동하는 단순한 시스템에서 진화 한 것으로 항상 밝혀졌습니다.
나는 git의 병합이 매우 정교하고 이해하기 매우 어려울 것이라고 생각합니다. 그러나 이에 접근하는 한 가지 방법은 그 선구자로부터 관심의 핵심에 초점을 맞추는 것입니다. 즉, 공통 조상이없는 두 개의 파일이 주어지면 git merge가 어떻게 파일을 병합하는지, 충돌이있는 위치를 파악합니까?
몇 가지 선구자를 찾아 보자. 에서 git help merge-file
:
git merge-file is designed to be a minimal clone of RCS merge; that is,
it implements all of RCS merge's functionality which is needed by
git(1).
wikipedia에서 : http://en.wikipedia.org/wiki/Git_%28software%29- > http://en.wikipedia.org/wiki/Three-way_merge#Three-way_merge- > http : //en.wikipedia .org / wiki / Diff3- > http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf
마지막 링크는 diff3
알고리즘을 자세히 설명하는 문서의 PDF입니다 . 다음은 google pdf-viewer 버전 입니다. 길이가 12 페이지에 불과하고 알고리즘은 몇 페이지에 불과하지만 완전한 수학적 처리입니다. 너무 형식적으로 보일 수 있지만 git의 병합을 이해하려면 먼저 간단한 버전을 이해해야합니다. 아직 확인하지 않았지만 같은 이름으로 diff3
diff ( 가장 긴 공통 하위 시퀀스 알고리즘 사용)를 이해해야 할 것입니다 . 그러나 diff3
Google이 있다면 더 직관적 인 설명이있을 수 있습니다 .
이제 저는 diff3
과 비교 실험 을했습니다 git merge-file
. 그들은 같은 3 개 개의 입력 파일을 가지고 버전 1 oldversion 버전 2 로, 그리고 마크 충돌하는 방식은 동일 <<<<<<< version1
, =======
, >>>>>>> version2
( diff3
도있다 ||||||| oldversion
), 공통의 유산을 보여주는.
나는에 대한 빈 파일을 사용 oldversion 등에 대한 거의 동일한 파일 버전 1 및 버전 2 단지 하나의 추가 라인에 추가 된 버전 2 .
결과 : git merge-file
변경된 단일 라인이 충돌로 식별되었습니다. 그러나 diff3
두 파일 전체를 충돌로 취급했습니다. 따라서 diff3처럼 정교하고 git의 병합은 가장 단순한 경우에도 훨씬 더 정교합니다.
실제 결과는 다음과 같습니다 (텍스트에 @twalberg의 답변을 사용했습니다). 필요한 옵션을 확인합니다 (해당 맨 페이지 참조).
$ git merge-file -p fun1.txt fun0.txt fun2.txt
You might be best off looking for a description of a 3-way merge algorithm. A
high-level description would go something like this:
Find a suitable merge base B - a version of the file that is an ancestor of
both of the new versions (X and Y), and usually the most recent such base
(although there are cases where it will have to go back further, which is one
of the features of gits default recursive merge) Perform diffs of X with B and
Y with B. Walk through the change blocks identified in the two diffs. If both
sides introduce the same change in the same spot, accept either one; if one
introduces a change and the other leaves that region alone, introduce the
change in the final; if both introduce changes in a spot, but they don't match,
mark a conflict to be resolved manually.
<<<<<<< fun1.txt
=======
THIS IS A BIT DIFFERENT
>>>>>>> fun2.txt
The full algorithm deals with this in a lot more detail, and even has some
documentation (/usr/share/doc/git-doc/technical/trivial-merge.txt for one,
along with the git help XXX pages, where XXX is one of merge-base, merge-file,
merge, merge-one-file and possibly a few others). If that's not deep enough,
there's always source code...
$ diff3 -m fun1.txt fun0.txt fun2.txt
<<<<<<< fun1.txt
You might be best off looking for a description of a 3-way merge algorithm. A
high-level description would go something like this:
Find a suitable merge base B - a version of the file that is an ancestor of
both of the new versions (X and Y), and usually the most recent such base
(although there are cases where it will have to go back further, which is one
of the features of gits default recursive merge) Perform diffs of X with B and
Y with B. Walk through the change blocks identified in the two diffs. If both
sides introduce the same change in the same spot, accept either one; if one
introduces a change and the other leaves that region alone, introduce the
change in the final; if both introduce changes in a spot, but they don't match,
mark a conflict to be resolved manually.
The full algorithm deals with this in a lot more detail, and even has some
documentation (/usr/share/doc/git-doc/technical/trivial-merge.txt for one,
along with the git help XXX pages, where XXX is one of merge-base, merge-file,
merge, merge-one-file and possibly a few others). If that's not deep enough,
there's always source code...
||||||| fun0.txt
=======
You might be best off looking for a description of a 3-way merge algorithm. A
high-level description would go something like this:
Find a suitable merge base B - a version of the file that is an ancestor of
both of the new versions (X and Y), and usually the most recent such base
(although there are cases where it will have to go back further, which is one
of the features of gits default recursive merge) Perform diffs of X with B and
Y with B. Walk through the change blocks identified in the two diffs. If both
sides introduce the same change in the same spot, accept either one; if one
introduces a change and the other leaves that region alone, introduce the
change in the final; if both introduce changes in a spot, but they don't match,
mark a conflict to be resolved manually.
THIS IS A BIT DIFFERENT
The full algorithm deals with this in a lot more detail, and even has some
documentation (/usr/share/doc/git-doc/technical/trivial-merge.txt for one,
along with the git help XXX pages, where XXX is one of merge-base, merge-file,
merge, merge-one-file and possibly a few others). If that's not deep enough,
there's always source code...
>>>>>>> fun2.txt
이것에 진정으로 관심이 있다면 약간의 토끼 구멍입니다. 나에게 그것은 정규 표현식, diff 의 가장 긴 공통 하위 시퀀스 알고리즘, 문맥 자유 문법 또는 관계 대수 만큼 깊어 보입니다 . 당신이 그것의 바닥에 도달하고 싶다면, 나는 당신이 할 수 있다고 생각하지만 결정적인 연구가 필요할 것입니다.