ฉันก็สนใจเหมือนกัน ฉันไม่รู้คำตอบ แต่ ...
ระบบที่ซับซ้อนที่ใช้งานได้มักจะพบว่ามีวิวัฒนาการมาจากระบบง่ายๆที่ใช้งานได้
ฉันคิดว่าการรวมกันของ 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 ของผู้ชม มีความยาวเพียง 12 หน้าและอัลกอริทึมมีเพียงไม่กี่หน้า - แต่เป็นการจัดการทางคณิตศาสตร์แบบเต็มรูปแบบ อาจดูเป็นทางการเกินไป แต่ถ้าคุณต้องการเข้าใจการผสานของ git คุณจะต้องเข้าใจเวอร์ชันที่ง่ายกว่าก่อน ฉันยังไม่ได้ตรวจสอบ แต่ด้วยชื่อที่ชอบdiff3
คุณอาจต้องเข้าใจความแตกต่างด้วย (ซึ่งใช้อัลกอริทึมลำดับต่อมาที่ยาวที่สุด ) อย่างไรก็ตามอาจมีคำอธิบายที่เข้าใจง่ายกว่าdiff3
นั้นหากคุณมี Google ...
ตอนนี้ผมก็ไม่ได้การทดลองเปรียบเทียบและdiff3
git merge-file
พวกเขาใช้เวลาเดียวกันแฟ้มใส่สามversion1 oldversion version2และเครื่องหมายความขัดแย้งทางเดียวกันกับ<<<<<<< version1
, =======
, >>>>>>> version2
( diff3
ยังมี||||||| oldversion
) แสดงให้เห็นมรดกร่วมกันของพวกเขา
ผมใช้ไฟล์ที่ว่างเปล่าสำหรับoldversionและไฟล์ที่อยู่ใกล้เหมือนกันสำหรับversion1และversion2ที่มีเพียงหนึ่งสายพิเศษที่เพิ่มการversion2
ผลลัพธ์: 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
หากคุณสนใจเรื่องนี้อย่างแท้จริงมันเป็นโพรงกระต่าย สำหรับฉันแล้วดูเหมือนว่าจะลึกพอ ๆ กับนิพจน์ทั่วไปอัลกอริธึมลำดับต่อมาที่ยาวที่สุดของความแตกต่างไวยากรณ์อิสระตามบริบทหรือพีชคณิตเชิงสัมพันธ์ ถ้าคุณต้องการที่จะไปถึงจุดสูงสุดฉันคิดว่าคุณทำได้ แต่จะต้องใช้การศึกษาอย่างตั้งใจ