Ben de ilgileniyorum. Cevabı bilmiyorum ama ...
Çalışan karmaşık bir sistemin her zaman çalışan basit bir sistemden evrimleştiği görülmüştür.
Bence git'in birleşmesi oldukça karmaşık ve anlaşılması çok zor - ancak buna yaklaşmanın bir yolu öncülerinden ve endişenizin özüne odaklanmaktır. Yani, ortak bir atası olmayan iki dosya verildiğinde, git merge bunları nasıl birleştireceğini ve çatışmaların nerede olduğunu nasıl çözer?
Bazı öncüler bulmaya çalışalım. Kimden 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'dan: 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
Bu son bağlantı, diff3
algoritmayı ayrıntılı olarak açıklayan bir makalenin pdfidir . İşte bir google pdf görüntüleyici sürümü . Sadece 12 sayfa uzunluğunda ve algoritma sadece birkaç sayfadan ibaret - ancak tam bir matematiksel işlem. Bu biraz fazla resmi görünebilir, ancak git'in birleştirmesini anlamak istiyorsanız, önce daha basit sürümü anlamanız gerekir. Henüz kontrol etmedim, ancak gibi bir adla diff3
muhtemelen diff ( en uzun ortak alt sıra algoritmasını kullanan) anlamanız gerekecek . Bununla birlikte, diff3
bir google'ınız varsa , orada daha sezgisel bir açıklama olabilir ...
Şimdi, diff3
ve karşılaştırarak bir deney yaptım git merge-file
. Bunlar aynı üç girdi dosyaları almak sürüm1 oldversion sürüm2 ile ve işareti çatışmaları yolu aynı <<<<<<< version1
, =======
, >>>>>>> version2
( diff3
aynı zamanda sahip ||||||| oldversion
), ortak mirasını gösteren.
Ben boş bir dosya kullanılan OldVersion ve için yakın özdeş dosyalar tipinde1 ve sürüm2 sadece bir fazladan satır ilave ile Version2 .
Sonuç: git merge-file
tek değiştirilen satırı çakışma olarak belirledi; ancak diff3
iki dosyayı da bir çatışma olarak değerlendirdi. Bu nedenle, diff3 kadar karmaşık olan git'in birleştirme işlemi, bu en basit durumlar için bile daha karmaşıktır.
İşte gerçek sonuçlar (metin için @ twalberg'in cevabını kullandım). Gerekli seçeneklere dikkat edin (ilgili yönetim sayfalarına bakın).
$ 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
Bununla gerçekten ilgileniyorsanız, biraz tavşan deliği. Bana göre, normal ifadeler kadar derin , diff'in en uzun ortak altdizisi algoritması, bağlamdan bağımsız gramerler veya ilişkisel cebir gibi görünüyor. Altına inmek istiyorsan, bence yapabilirsin, ama biraz kararlı çalışma gerektirecek.