Ich bin auch interessiert. Ich weiß die Antwort nicht, aber ...
Ein komplexes System, das funktioniert, hat sich aus einem einfachen System entwickelt, das funktioniert hat
Ich denke, die Verschmelzung von git ist hochentwickelt und wird sehr schwer zu verstehen sein - aber eine Möglichkeit, dies zu erreichen, sind die Vorläufer und die Konzentration auf das Herz Ihres Anliegens. Das heißt, bei zwei Dateien, die keinen gemeinsamen Vorfahren haben, wie funktioniert Git Merge, wie sie zusammengeführt werden und wo Konflikte auftreten?
Versuchen wir, einige Vorläufer zu finden. Von 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).
Aus 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
Dieser letzte Link ist ein PDF eines Papiers, das den diff3
Algorithmus im Detail beschreibt. Hier ist eine Google PDF-Viewer-Version . Es ist nur 12 Seiten lang und der Algorithmus ist nur ein paar Seiten lang - aber eine umfassende mathematische Behandlung. Das mag etwas zu formal erscheinen, aber wenn Sie die Zusammenführung von git verstehen möchten, müssen Sie zuerst die einfachere Version verstehen. Ich habe es noch nicht überprüft, aber mit einem Namen wie diff3
müssen Sie wahrscheinlich auch diff verstehen (das einen längsten gemeinsamen Subsequenzalgorithmus verwendet). Es kann jedoch eine intuitivere Erklärung diff3
geben, wenn Sie eine Google ...
Jetzt habe ich gerade ein Experiment durchgeführt diff3
und git merge-file
. Sie nehmen die gleichen drei Eingabedateien version1 oldversion version2 und markieren Konflikte die Art und Weise gleich, mit <<<<<<< version1
, =======
, >>>>>>> version2
( diff3
auch hat ||||||| oldversion
), ihr gemeinsames Erbe zeigt.
Früher habe ich eine leere Datei für oldversion und nahezu identische Dateien für version1 und version2 mit nur einem zusätzlichen Zeile hinzugefügt version2 .
Ergebnis: git merge-file
identifizierte die einzelne geänderte Zeile als Konflikt; diff3
behandelte aber die ganzen zwei Dateien als Konflikt. So ausgefeilt diff3 auch ist, die Zusammenführung von git ist selbst in diesem einfachsten Fall noch ausgefeilter.
Hier sind die tatsächlichen Ergebnisse (ich habe die Antwort von @ twalberg für den Text verwendet). Beachten Sie die benötigten Optionen (siehe entsprechende Seiten).
$ 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
Wenn Sie wirklich daran interessiert sind, ist es ein bisschen wie ein Kaninchenbau. Für mich scheint es so tief wie reguläre Ausdrücke, der längste gängige Subsequenzalgorithmus für Diff, kontextfreie Grammatiken oder relationale Algebra. Wenn Sie dem auf den Grund gehen wollen, können Sie es meiner Meinung nach, aber es wird einige entschlossene Studien erfordern.