มีความแตกต่างระหว่างการผสานใน svn เมื่อเปรียบเทียบกับ git หรือ mercurial หรือไม่?


12

จากความเข้าใจของฉัน SVN คือ 'ง่ายต่อการแตกสาขา ยากที่จะรวม ' ทำไมถึงเป็นอย่างนั้น? มีวิธีแตกต่างกันอย่างไร?

git  svn  mercurial  dvcs 

คำตอบ:


21

โปรดดูคำตอบสแต็คล้นของฉันสำหรับสถานการณ์ที่เป็นรูปธรรมมากที่ Mercurial (และ Git) ผสานเข้าด้วยกันโดยไม่มีปัญหาและที่ Subversion นำเสนอคุณด้วยความขัดแย้งปลอม สถานการณ์เป็นการปรับโครงสร้างอย่างง่ายที่กระทำบนสาขาที่คุณเปลี่ยนชื่อไฟล์บางไฟล์

เมื่อพิจารณาถึงคำตอบของ tdammers แล้วมีจำนวนของความเข้าใจผิดที่นั่น:

  • การโค่นล้ม Mercurial และ Git สแน็ปช็อตกว้างของที่เก็บแทร็กทั้งหมดของโครงการ เรียกพวกเขารุ่น , การแก้ไขหรือการแก้ไขทำให้ไม่แตกต่าง พวกมันเป็นภาพรวมเชิงอะตอมของชุดของไฟล์

  • ขนาดของการผูกมัดของคุณไม่ได้ต่างไปจากการรวมเข้าด้วยกัน ทั้งสามระบบผสานกับอัลกอริธึมการผสานสามทางมาตรฐานและอินพุตของอัลกอริทึมนั้น

    • รุ่นบรรพบุรุษที่ยิ่งใหญ่ที่สุดที่พบบ่อย
    • รุ่นหนึ่งสาขา
    • รุ่นที่สาขาอื่น ๆ

    มันไม่สำคัญว่าทั้งสองรุ่นสาขาที่ถูกสร้างขึ้น คุณสามารถใช้การคอมมิตขนาดเล็กได้ 1,000 ครั้งตั้งแต่เวอร์ชันบรรพบุรุษหรือคุณสามารถใช้การคอมมิท 1 ครั้งได้ สิ่งที่สำคัญคือไฟล์เวอร์ชันสุดท้าย (ใช่นี่เป็นเรื่องที่น่าประหลาดใจใช่แล้วคู่มือ DVCS จำนวนมากจะทำสิ่งนี้ผิดไปอย่างน่ากลัว)

เขายังยกประเด็นที่ดีเกี่ยวกับความแตกต่าง:

  • การโค่นล้มมีบางส่วน "ของขึ้น" ที่คุณสามารถผสานจากลงในการพูด/trunk /branches/fooMercurial และ Git ไม่ได้ใช้โมเดลนี้ - กิ่งก้านเป็นแบบจำลองโดยตรงในประวัติศาสตร์ ประวัติจึงกลายเป็นกราฟชีทกำกับแทนที่จะเป็นเส้นตรง นี่เป็นรุ่นที่ง่ายกว่ารุ่นที่ใช้โดยการโค่นล้มและจะตัดมุมกรณีจำนวนหนึ่งออกไป

  • คุณสามารถชะลอการรวมหรือปล่อยให้คนอื่นจัดการได้อย่างง่ายดาย หากhg mergeคุณมีข้อขัดแย้งมากมายคุณสามารถขอให้เพื่อนร่วมงานของคุณhg pullจากคุณและเขาก็มีสถานะเดียวกัน ดังนั้นเขาสามารถhg mergeและบางทีเขาอาจจะดีกว่าในการแก้ไขความขัดแย้งมากกว่าที่คุณเป็น

    นี่เป็นเรื่องยากมากกับการโค่นล้มที่คุณต้องอัปเดตก่อนที่จะส่งมอบ คุณไม่สามารถเพิกเฉยต่อการเปลี่ยนแปลงบนเซิร์ฟเวอร์และกระทำการกับสาขาที่ไม่ระบุชื่อของคุณเอง โดยทั่วไปกองกำลังโค่นล้มคุณที่จะเล่นรอบกับสำเนาการทำงานสกปรกsvn updateเมื่อคุณ สิ่งนี้มีความเสี่ยงเนื่องจากคุณไม่ได้จัดเก็บการเปลี่ยนแปลงของคุณไว้อย่างปลอดภัย Git และ Mercurial ให้คุณยอมรับก่อนจากนั้นอัปเดตและผสานตามความจำเป็น

เหตุผลที่แท้จริง Git และ Mercurial นั้นดีกว่าการควบรวมมากกว่าการโค่นล้มเป็นเรื่องของการดำเนินการ มีการเปลี่ยนชื่อความขัดแย้งที่การโค่นล้มไม่สามารถจัดการได้แม้จะคิดว่ามันชัดเจนว่าคำตอบที่ถูกต้องคืออะไร Mercurial และ Git จัดการสิ่งเหล่านั้นได้อย่างง่ายดาย แต่ไม่มีเหตุผลว่าทำไมการโค่นล้มไม่สามารถจัดการกับสิ่งเหล่านั้นได้ดี - การรวมศูนย์ไม่ใช่เหตุผลอย่างแน่นอน


4
คำตอบที่ดี! ฉันจะโหวตสองครั้งถ้าทำได้ :) ฉันยังเพิ่มว่าหนังสือ SVN ที่คุณอ้างถึงในคำตอบนั้นยอมรับอย่างชัดเจนว่า"คุณสมบัติการติดตามการโค่นล้มของ Subversion มีการใช้งานภายในที่ซับซ้อนอย่างยิ่ง ... " - เพียงอย่างเดียวนี่เป็นการบ่งชี้ที่ดีทีเดียวว่าคุณลักษณะไม่น่าเชื่อถือ
gnat

2
... และถึงแม้จะมีการนำไปใช้ที่ซับซ้อนอย่างมากก็ไม่สามารถคิดได้ว่าบรรพบุรุษร่วมกันถูกต้องในทุกกรณี แต่อย่างง่าย
Jan Hudec

เกี่ยวกับการรวมที่ล่าช้า - ไม่เข้าใจ - ด้วย SVN เพื่อนร่วมงานของฉันสามารถอัปเดตเป็น / เช็คเอาต์ลำต้นและรวมจากสาขาของฉันเข้าด้วยกัน
Gates Bates

@GillBates: ฉันกำลังพูดถึงสถานการณ์ที่คุณไม่ได้เริ่มสาขาสำหรับงานของคุณ - เมื่อคุณกำลังทำงานtrunkใน SVN ด้วย DVCS คุณสามารถกระทำได้โดยไม่ต้องแชร์ แต่ใน SVN คุณsvn commitจะส่งผลโดยตรงต่อผู้อื่นที่ทำงานในสาขาเดียวกัน แม้ว่าเราสองคนทำงานในสาขาใน SVN ฉันไม่สามารถทำงานของฉันได้โดยไม่ต้องรวมงานของคุณเข้าด้วยกันทันที นั่นทำให้คอมมิทค่อนข้างน่ากลัว - ซึ่งเป็นคุณสมบัติที่น่ากลัวสำหรับระบบควบคุมเวอร์ชัน! :-)
Martin Geisler

6

ปัญหาหลักอยู่ที่วิธีที่ระบบเหล่านี้แสดงถึงโครงสร้างไดเรกทอรีที่มีเวอร์ชัน

แนวคิดพื้นฐานของการโค่นล้มซึ่งระบบทั้งหมดหมุนรอบตัวเป็นของเวอร์ชัน (หรือใน svn lingo, "revision"): สแน็ปช็อตของไฟล์ ณ จุดหนึ่ง ตราบใดที่ประวัติศาสตร์เป็นเส้นตรงอย่างสมบูรณ์ทุกอย่างก็ดี แต่ถ้าคุณต้องการรวมการเปลี่ยนแปลงจากสองสายการพัฒนาอิสระ svn ต้องเปรียบเทียบเวอร์ชันปัจจุบันของทั้งคู่แล้วทำการเปรียบเทียบสามทางระหว่างเวอร์ชันที่แชร์ล่าสุด และสองรุ่นใหญ่ บรรทัดที่ปรากฏในหัวหนึ่ง แต่ไม่สามารถแก้ไขได้อย่างง่ายดาย เส้นที่เบี่ยงเบนไปในทางเดียวกันทั้งสองหัวนั้นยากกว่า แต่มักเป็นไปได้ บรรทัดที่เบี่ยงเบนในรูปแบบที่แตกต่างกันคือสิ่งที่ทำให้ svn พูดว่า "ฉันไม่สามารถเข้าใจสิ่งนี้ได้มนุษย์โปรดแก้ไขสิ่งนี้ให้ฉันด้วย"

ในทางตรงกันข้ามคอมไพล์และติดตามปรอทการแก้ไขมากกว่ารุ่น ที่เก็บทั้งหมดเป็นแผนผังของเซ็ตการแก้ไขแต่ละอันขึ้นอยู่กับพาเรนต์ซึ่งเซ็ตการแก้ไขพาเรนต์สามารถมีลูกได้จำนวนเท่าใดก็ได้และรากของต้นไม้แสดงถึงไดเร็กทอรีว่าง กล่าวอีกนัยหนึ่ง git / hg กล่าวว่า "ก่อนอื่นฉันไม่มีอะไรเลยโปรแกรมแก้ไขนี้จะถูกนำไปใช้งานจากนั้นก็เป็นโปรแกรมแก้ไขดังกล่าว ฯลฯ " เมื่อคุณต้องการผสานการพัฒนาสองบรรทัด git / hg ไม่เพียง แต่รู้ว่าหัวแต่ละคนในปัจจุบันมีลักษณะอย่างไรและดูเหมือนรุ่นทั่วไปที่ผ่านมาอย่างไรมันก็รู้ว่าการเปลี่ยนแปลงเกิดขึ้นได้อย่างไร

อีกสิ่งหนึ่งที่ทำให้การรวมกันง่ายขึ้นใน DVCS คือผลลัพธ์ทางอ้อมของการแยกแนวคิดของการกระทำและการผลักดันและอนุญาตให้มีการรวมข้ามทุกประเภทระหว่างสองโคลนของที่เก็บเดียวกันได้ตลอดเวลา ด้วย svn ผู้คนมักจะทำการเซ็ตอัพเซ็ตขนาดใหญ่ที่มีการเปลี่ยนแปลงที่ไม่เกี่ยวข้องบ่อยครั้งเนื่องจากคอมมิชชันยังเป็นการอัพเดตบนที่เก็บส่วนกลางซึ่งมีผลต่อสมาชิกในทีมอื่น ๆ ทั้งหมด; หากคุณส่งเวอร์ชั่นที่แตกสลายทุกคนจะโกรธคุณ เนื่องจากการตั้งค่าส่วนใหญ่เกี่ยวข้องกับเซิร์ฟเวอร์ svn เครือข่ายการส่งข้อมูลจึงเกี่ยวข้องกับการปั๊มข้อมูลผ่านเครือข่ายซึ่งหมายความว่าการส่งข้อมูลจะทำให้เกิดความล่าช้าในเวิร์กโฟลว์ (โดยเฉพาะเมื่อสำเนาการทำงานของคุณล้าสมัยและคุณต้องดึงก่อน) ด้วยคอมไพล์และเมอร์คิวเรียนคอมมิชชันเกิดขึ้นแบบโลคอลและเนื่องจากทั้งคู่มีประสิทธิภาพมากในการจัดการระบบไฟล์ในท้องถิ่นจึงมักจะเสร็จสิ้นในทันที เป็นผลให้ผู้คน (เมื่อพวกเขาคุ้นเคยกับมัน) จะทำการเปลี่ยนแปลงที่เพิ่มขึ้นเล็กน้อยจากนั้นเมื่อมันทำงาน ผลักดันโหลหรือมากกว่านั้นมุ่งมั่นในครั้งเดียว จากนั้นเมื่อรวมเวลาเข้ามา SCM จะมีข้อมูลที่ละเอียดมากยิ่งขึ้นไปอีกและสามารถแก้ไขข้อขัดแย้งของงานได้อย่างปลอดภัยและอัตโนมัติ

แล้วมีรายละเอียดที่ดีที่ทำให้สิ่งต่าง ๆ ง่ายขึ้น:

  • คุณสามารถมีหลายหัวและยังคงมุ่งมั่นกับ; ซึ่งแตกต่างจากการโค่นล้มคุณไม่จำเป็นต้องรวม pull, update และ merge ก่อนที่จะคอมมิทอีกครั้ง - หัวหลาย ๆ อันนั้นคงอยู่จนกว่าคุณจะเลือกที่จะผสาน
  • ไดเรกทอรีไม่ได้รับการดูแลเป็นพิเศษ แต่เส้นทางนั้นถือว่าเป็นชื่อไฟล์ขนาดใหญ่เพียงหนึ่งไฟล์และไดเรกทอรีทั้งหมดของคุณจะต้องได้รับการแก้ไขแบบเดียวกันตลอดเวลา ซึ่งหมายความว่าคุณไม่สามารถทำวูดูรุ่นย่อยที่มีโฟลเดอร์ย่อยของโปรเจ็กต์ต่าง ๆ ได้ แต่ก็หมายความว่าสำเนาที่ใช้งานมีโอกาสน้อยที่จะกลายเป็นระเบียบที่ไม่สามารถจัดการได้ขนาดใหญ่และน่าสนใจกว่า - และ - เพิ่ม (ซึ่งจะแบ่งออกเป็น svn ทั้งหมดหากไม่ใช่เมตาดาต้า retrofit) แต่เป็นการเปลี่ยนชื่อ หากคุณย้ายไฟล์ประวัติทั้งหมดจะถูกเก็บไว้ การผสานสามารถนำการเปลี่ยนแปลงไปใช้กับไฟล์ที่ถูกย้ายซึ่งทำกับเวอร์ชันที่ไม่ย้ายของไฟล์เดียวกันหลังจากการย้ายในสาขาอื่น
  • ส่วนใหญ่แล้วคุณไม่จำเป็นต้องแยกสาขา แต่จริงๆแล้วคุณเพียงแค่ทำการโคลนพื้นที่เก็บข้อมูลทั้งหมด การโคลนนิ่งมีราคาถูกโดยเฉพาะอย่างยิ่งถ้ามันทำในระบบไฟล์เดียวกันและถ้าคุณตัดสินใจว่าจะกำจัดโคลนคุณแค่ลบไดเรกทอรีที่อยู่ในนั้น คุณไม่จำเป็นต้องใช้ hg หรือ git
  • มีข้อ จำกัด เล็กน้อย (ถ้ามี) ในสิ่งที่คุณสามารถผสานได้ คุณสามารถมีหกโคลนของพื้นที่เก็บข้อมูลเดียวกันและผสาน (หรือค่อนข้างดันหรือดึง; การผสานที่ชัดเจนมักจะไม่จำเป็นต้องใช้) จาก A ถึง B จากนั้น C ถึง B จากนั้น B ถึง D จากนั้น C ถึง D, B กลับ ถึง A, D ถึง E ได้ตลอดเวลาและบ่อยเท่าที่คุณต้องการ
  • คุณสามารถทดสอบการผสานได้โดยการโคลนที่เก็บข้อมูลอันใดอันหนึ่งที่คุณต้องการผสานแล้วดึงลงมาจากที่อื่น ถ้ามันทำในสิ่งที่คุณต้องการคุณสามารถผลักดันกลับไปสู่เป้าหมายที่แท้จริงได้ถ้าไม่ทำคุณทิ้งโคลนและเริ่มใหม่อีกครั้ง

2
ฉันต้องพูดถึงการแก้ไขบางอย่างและเพิ่มที่จะตอบ: 1. การแก้ไข SVN เป็นส่วนกลางต่อพื้นที่เก็บข้อมูลการแก้ไขแสดงไฟล์ทั้งหมดใน repo ในบางช่วงเวลา 2. เทคโนโลยีการผสานเป็นเรื่องธรรมดาโดยทั่วไปใน SVN และ DVCS - หากไฟล์ในไฟล์ผสานเปลี่ยนแปลงเท่านั้น วิธีเดียวกันการผสานจะสร้างความขัดแย้งจำนวนเท่ากันสำหรับ SVN และ DVCS - SCM ทั้งหมดยังคงทำงานในระดับสตริงไม่ใช่บล็อกเชิงตรรกะ 3. การยอมรับขนาดใหญ่ใน SVN ไม่ใช่ผลมาจากความอ่อนแอทางสถาปัตยกรรม แต่เนื่องจากผู้ใช้มักเป็นคนขี้เกียจ - พวกเขาไม่สนใจรูปแบบพื้นฐาน สาขา | ผสานทำงานใน SVN หาก / dev / สมองและ / dev / hands ทำงาน
Lazy Badger

2
ส่วนที่ 2: การรวมอัจฉริยะใน DVCS ส่วนใหญ่เกิดขึ้นเพราะตรงกันข้ามกับการโค่นล้มพวกเขาติดตามและจัดการการย้าย | การเปลี่ยนชื่อไฟล์และ SVN ไม่ได้ทำเลยดังนั้น - การดำเนินการใด ๆ ซึ่งกระบวนการไฟล์เปลี่ยนด้านหนึ่งและเปลี่ยนชื่อ ที่สองจะล้มเหลว การแยกสาขากับสาขาและมีการโคลนนิ่งเป็นเพียงกลยุทธ์ที่แตกต่างกันในการแยกสาขาที่มีสิทธิ์เหมือนกันสำหรับการใช้ชีวิตซึ่งจะใช้ "... ขึ้นอยู่กับ ... "
Lazy Badger

@ LazyBadger: Au contraire การโค่นล้มจะติดตามการย้าย / เปลี่ยนชื่อซึ่งเป็นสาเหตุของความขัดแย้งส่วนหนึ่งเนื่องจากการจัดการการเปลี่ยนชื่อในการผสานนั้นเป็นเพียงแค่บั๊กกี้และอีกส่วนหนึ่งเนื่องจากมีกรณีมุมที่ยากหรือเป็นไปไม่ได้ที่จะจัดการอย่างถูกต้อง ต่อมาคือเหตุผลที่คอมไพล์ (และปรอทคัดลอกมัน) โดยการออกแบบไม่ได้ติดตามการเปลี่ยนชื่อและคาดเดาพวกเขาเมื่อรวม ซึ่งทำงานได้ดีหากเนื้อหายังคล้ายกันมากพอที่จะผสาน (ซึ่งก็คือเมื่อคุณต้องการ) และไม่ทำสิ่งที่โง่เขลา
Jan Hudec

@JanHudec - ขอโทษ SVN จัดการไม่ย้าย | เปลี่ยนชื่อที่atomic one action (วิธี DVCS - "เปลี่ยนชื่อ") แต่เป็น "delete + ... " ดังนั้นจึงสร้างความขัดแย้งของต้นไม้ซึ่งจะไม่เกิดขึ้นใน DVCS (การเปลี่ยนชื่อจริง ) Mercurial ติดตามเปลี่ยนชื่ออย่างชัดเจน ( hg mvหรือhg addremove --similarity...) ในขณะที่ Git ใช้แก้ปัญหา แต่ทั้งสองจับเปลี่ยนชื่อ ฉันสามารถรับความขัดแย้งของต้นไม้ได้แม้จะมีความแตกต่างของสตริง 1ไฟล์ในการรวมกัน! คุณต้องเรียนรู้แง่มุมการโค่นล้มอีกครั้ง
Lazy Badger

5
ตอนนี้เราได้รับเทคนิคค่อนข้างมาก :-) ทั้งการโค่นล้มการติดตามและการคัดลอก Mercurial ไม่ใช่การเปลี่ยนชื่อ ทั้งสองระบบติดตามrename a bฐานะcopy a b; remove aและทั้งสองจะทำมันในหนึ่งอะตอมกระทำ พฤติกรรมการผสานที่แตกต่างกันนั้นเกิดจากการใช้งานมุมและการโค่นล้มที่แตกต่างกันทำให้เกิดการรวมกันมากกว่า Mercurial และ Git ในที่สุด Git ตรวจจับการเปลี่ยนชื่อที่รวมและเวลาเข้าสู่ระบบ - เรากำลังคิดที่จะเพิ่มสิ่งนี้ใน Mercurial ด้วย
Martin Geisler
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.