Мені теж цікаво. Я не знаю відповіді, але ...
Незмінно виявляється, що складна система, яка працює, еволюціонувала із простої системи, яка працювала
Я думаю, що злиття 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
Це останнє посилання є PDF-документом із diff3
детальним описом алгоритму. Ось версія google pdf-viewer . Він займає всього 12 сторінок, а алгоритм - лише пару сторінок - але повноцінна математична обробка. Це може здатися дещо надто офіційним, але якщо ви хочете зрозуміти злиття git, вам потрібно спочатку зрозуміти простішу версію. Я ще не перевіряв, але з таким іменем diff3
, напевно, вам також потрібно буде зрозуміти diff (який використовує найдовший загальний алгоритм послідовності ). Однак, можливо, є більш інтуїтивне пояснення diff3
, якщо у вас є Google ...
Тепер я просто зробив експеримент, порівнюючи diff3
і git merge-file
. Вони приймають одні і ті ж три вхідних файлу version1 oldversion Version2 і оцінка конфліктів Те , як же, з <<<<<<< version1
, =======
, >>>>>>> version2
( diff3
також ||||||| 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
Якщо ви справді зацікавлені в цьому, це трохи кроляча нора. Для мене це здається таким глибоким, як регулярні вирази, найдовший загальний алгоритм підпослідовності різниці, без контексту граматики або реляційної алгебри. Якщо ви хочете докластися до його суті, я думаю, що можете, але для цього знадобиться певне рішуче дослідження.