Мне тоже интересно. Я не знаю ответа, но ...
Сложная работающая система неизменно эволюционировала из простой системы, которая работала.
Я думаю, что слияние 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).
Из википедии: 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
Эта последняя ссылка представляет собой PDF-документ с diff3
подробным описанием алгоритма. Вот версия для Google pdf-viewer . Это всего лишь 12 страниц, а алгоритм - всего пара страниц - но полная математическая обработка. Это может показаться слишком формальным, но если вы хотите понять слияние git, вам сначала нужно понять более простую версию. Я еще не проверял, но с таким именем diff3
вам, вероятно, также понадобится понять diff (который использует самый длинный общий алгоритм подпоследовательности ). Однако может быть более интуитивное объяснение diff3
, если у вас есть Google ...
Я просто провел эксперимент, сравнивая diff3
и git merge-file
. Они принимают одни и те же три входных файла version1 oldversion Version2 и оценка конфликтов То , как же, с <<<<<<< version1
, =======
, >>>>>>> version2
( diff3
также ||||||| oldversion
), показывая их общее наследие.
Я использовал пустой файл для oldversion , а также файлы почти одинаковые для version1 и version2 с добавлением только одна дополнительная линия Version2 .
Результат: git merge-file
идентифицирована единственная измененная строка как конфликт; но diff3
рассматривал все два файла как конфликт. Таким образом, git merge, столь же сложный, как diff3, еще сложнее даже для этого простейшего случая.
Вот фактические результаты (я использовал ответ @ 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, контекстно-свободные грамматики или реляционная алгебра. Если вы хотите разобраться в этом, я думаю, вы сможете, но это потребует определенного исследования.