Git and Mercurial - เปรียบเทียบและความเปรียบต่าง


520

ในขณะนี้ฉันใช้การโค่นล้มสำหรับโครงการส่วนตัวของฉัน

มากขึ้นเรื่อย ๆ ฉันได้ยินสิ่งดีๆเกี่ยวกับ Git และ Mercurial และ DVCS โดยทั่วไป

ฉันต้องการให้สิ่งที่ DVCS ทั้งหมดเป็นเรื่องวน แต่ฉันก็ไม่คุ้นเคยกับตัวเลือกทั้งสอง

Mercurial และ Git ต่างกันอย่างไร?

หมายเหตุ: ฉันไม่ได้พยายามหาว่าอันไหนที่ "ดีที่สุด" หรือแม้แต่อันที่ฉันควรเริ่มต้นด้วย ฉันกำลังมองหาพื้นที่สำคัญที่พวกเขามีลักษณะคล้ายกันและที่พวกเขาแตกต่างกันเพราะฉันสนใจที่จะรู้ว่าพวกเขาแตกต่างกันในแง่ของการดำเนินงานและปรัชญา



2
ความเป็นไปได้ที่ซ้ำซ้อนของMercurial และ Git คืออะไร
nawfal

คำตอบ:


451

ข้อจำกัดความรับผิดชอบ: ฉันใช้ Git ติดตามการพัฒนา Git ในรายชื่อผู้รับจดหมาย git และสนับสนุน bit ให้กับ Git (gitweb เป็นหลัก) ฉันรู้ Mercurial จากเอกสารและบางอย่างมาจากการอภิปรายในช่อง #revctrl IRC บน FreeNode

ขอบคุณทุกคนใน #mercurial IRC channel ที่ให้ความช่วยเหลือเกี่ยวกับ Mercurial สำหรับการเขียนนี้



สรุป

ที่นี่มันจะดีถ้ามี syntax สำหรับ table เช่นใน PHPMarkdown / MultiMarkdown / Maruku ส่วนขยายของ Markdown

  • โครงสร้างที่เก็บข้อมูล: Mercurial ไม่อนุญาตให้รวมปลาหมึกยักษ์ (กับพ่อแม่มากกว่าสองคน) หรือการติดแท็กวัตถุที่ไม่ส่งมอบ
  • แท็ก: Mercurial ใช้.hgtagsไฟล์ที่มีเวอร์ชันพร้อมกฎพิเศษสำหรับแท็กต่อพื้นที่เก็บข้อมูลและยังรองรับแท็กท้องถิ่น.hg/localtagsด้วย ในแท็ก Git นั้นอ้างอิงอยู่ในrefs/tags/เนมสเปซและโดยค่าเริ่มต้นจะมีการติดตามอัตโนมัติในการดึงข้อมูลและต้องการการผลักดันอย่างชัดเจน
  • สาขาใน Mercurial พื้นฐานขั้นตอนการทำงานจะขึ้นอยู่กับหัวที่ไม่ระบุชื่อ ; Git ใช้กิ่งไม้ที่มีน้ำหนักเบาและมีสาขาพิเศษ ( สาขาติดตามระยะไกล ) ที่ติดตามสาขาในที่เก็บระยะไกล
  • การตั้งชื่อและช่วงการแก้ไขใหม่: Mercurial ให้หมายเลขการแก้ไขท้องถิ่นไปยังที่เก็บและฐานการแก้ไขที่เกี่ยวข้อง (นับจากส่วนปลายเช่นสาขาปัจจุบัน) และช่วงการแก้ไขสำหรับหมายเลขท้องถิ่นนี้ Git นำเสนอวิธีการอ้างถึงการแก้ไขที่สัมพันธ์กับปลายกิ่งและช่วงการแก้ไขเป็นทอพอโลยี (ขึ้นอยู่กับกราฟของการแก้ไข)
  • Mercurial ใช้การติดตามการเปลี่ยนชื่อในขณะที่ Git ใช้การตรวจจับการเปลี่ยนชื่อเพื่อจัดการกับการเปลี่ยนชื่อไฟล์
  • เครือข่าย: Mercurial รองรับโปรโตคอล SSH และ HTTP "สมาร์ท" และโปรโตคอล HTTP แบบคงที่ modern Git รองรับโปรโตคอล SSH, HTTP และ GIT "สมาร์ท" และโปรโตคอล HTTP "S" dumb " ทั้งสองรองรับไฟล์บันเดิลสำหรับการส่งแบบออฟไลน์
  • Mercurial ใช้ส่วนขยาย (ปลั๊กอิน) และ API ที่สร้างขึ้น Git มีความสามารถในการเขียนสคริปต์และรูปแบบที่กำหนดไว้

มีบางสิ่งที่แตกต่างจาก Mercurial จาก Git แต่มีสิ่งอื่นที่ทำให้พวกมันเหมือนกัน ทั้งสองโครงการยืมแนวคิดจากกันและกัน ยกตัวอย่างเช่นhg bisectคำสั่งใน Mercurial (เดิมนามสกุลแบ่งครึ่ง ) คือแรงบันดาลใจจากgit bisectคำสั่งใน Git ในขณะที่ความคิดของการเป็นแรงบันดาลใจgit bundlehg bundle

โครงสร้างที่เก็บการจัดเก็บการแก้ไข

ใน Git มีวัตถุสี่ประเภทในฐานข้อมูลวัตถุ: วัตถุblobที่มีเนื้อหาของไฟล์วัตถุต้นไม้ลำดับชั้นที่จัดเก็บโครงสร้างไดเรกทอรีรวมถึงชื่อไฟล์และส่วนที่เกี่ยวข้องของการอนุญาตไฟล์ (สิทธิ์การปฏิบัติการสำหรับไฟล์เป็นลิงค์สัญลักษณ์) , กระทำวัตถุซึ่งมีข้อมูลประพันธ์ชี้ไปยังภาพรวมของสถานะของพื้นที่เก็บข้อมูลในการแก้ไขแสดงโดยกระทำ (ผ่านวัตถุต้นไม้ของไดเรกทอรีบนของโครงการ) และการอ้างอิงถึงศูนย์หรือมากกว่ากระทำของผู้ปกครองและแท็กวัตถุซึ่งอ้างอิงวัตถุอื่น ๆ และสามารถ สามารถลงนามโดยใช้ PGP / GPG

Git ใช้วิธีการเก็บวัตถุสองวิธี: รูปแบบหลวมที่แต่ละวัตถุถูกเก็บไว้ในไฟล์แยกต่างหาก (ไฟล์เหล่านั้นถูกเขียนเพียงครั้งเดียวและไม่เคยแก้ไข) และรูปแบบที่บรรจุซึ่งวัตถุจำนวนมากถูกเก็บเดลต้าบีบอัดไว้ในไฟล์เดียว ความเป็นจริงของการดำเนินการของอะตอมมิกคือการอ้างอิงถึงวัตถุใหม่นั้นถูกเขียนขึ้น (แบบอะตอมใช้การสร้าง + เปลี่ยนชื่อเคล็ดลับ) หลังจากเขียนวัตถุ

ที่เก็บ Git ต้องการการบำรุงรักษาเป็นระยะโดยใช้git gc(เพื่อลดพื้นที่ดิสก์และปรับปรุงประสิทธิภาพ) แม้ว่าปัจจุบัน Git จะทำเช่นนั้นโดยอัตโนมัติ (วิธีนี้ให้การบีบอัดที่เก็บที่ดีกว่า)

Mercurial (เท่าที่ฉันเข้าใจ) เก็บประวัติของไฟล์ในfilelog (ด้วยกันฉันคิดว่ามีเมทาดาทาพิเศษเช่นการเปลี่ยนชื่อการติดตามและข้อมูลผู้ช่วยบางส่วน); มันใช้โครงสร้างแบนที่เรียกว่ารายการที่จะจัดเก็บโครงสร้างไดเรกทอรีและโครงสร้างที่เรียกว่าchangelogซึ่งเก็บข้อมูลเกี่ยวกับการเปลี่ยนแปลง (แก้ไข) รวมถึงการกระทำข้อความและศูนย์พ่อแม่หนึ่งหรือสอง

Mercurial ใช้เจอร์นัลธุรกรรมเพื่อจัดเตรียมอะตอมมิกของการดำเนินการและอาศัยการตัดทอนไฟล์เพื่อล้างข้อมูลหลังจากการดำเนินการล้มเหลวหรือถูกขัดจังหวะ Revlogs เป็นแบบต่อท้ายเท่านั้น

เมื่อดูที่โครงสร้างของที่เก็บใน Git กับ Mercurial เราจะเห็นได้ว่า Git นั้นเป็นเหมือนฐานข้อมูลวัตถุ (หรือระบบไฟล์ที่แก้ไขเนื้อหา) และ Mercurial ก็เหมือนกับฐานข้อมูลเชิงสัมพันธ์คงที่แบบดั้งเดิม

ความแตกต่าง:
ใน Git วัตถุต้นไม้ในรูปแบบโครงสร้างลำดับชั้น ; ในไฟล์ Mercurial manifestเป็นโครงสร้างแบบแบน ในที่เก็บวัตถุGit blob หนึ่งรุ่นของเนื้อหาของไฟล์ ใน Mercurial filelogเก็บประวัติทั้งหมดของไฟล์เดียว (หากเราไม่ได้คำนึงถึงความซับซ้อนของการเปลี่ยนชื่อ) ซึ่งหมายความว่ามีพื้นที่ต่าง ๆ ของการดำเนินการที่ Git จะเร็วกว่า Mercurial ทุกสิ่งอื่น ๆ ถือว่าเท่าเทียมกัน (เช่นการรวมหรือแสดงประวัติของโครงการ) และพื้นที่ที่ Mercurial จะเร็วกว่า Git (เช่นการใช้แพทช์หรือการแสดง ประวัติของไฟล์เดียว)ปัญหานี้อาจไม่สำคัญสำหรับผู้ใช้

เนื่องจากโครงสร้างบันทึกคงที่ของโครงสร้างการเปลี่ยนแปลงของ Mercurial การกระทำใน Mercurial จึงสามารถมีผู้ปกครองได้สูงสุดสองคนเท่านั้น คอมมิทใน Git สามารถมีพ่อแม่ได้มากกว่าสองคน (เรียกว่า "octopus merge") ในขณะที่คุณสามารถ (ในทางทฤษฎี) แทนที่ octopus merge ด้วยชุดของการรวมกันของสองพาเรนต์ แต่สิ่งนี้อาจทำให้เกิดความยุ่งยากเมื่อทำการแปลงระหว่างที่เก็บ Mercurial และ Git

เท่าที่ฉันทราบ Mercurial ไม่มีแท็กหมายเหตุประกอบ (วัตถุแท็ก) จาก Git กรณีพิเศษของแท็กที่มีคำอธิบายประกอบเป็นแท็กที่ลงนามแล้ว (ที่มีลายเซ็น PGP / GPG); สามารถเทียบเท่าใน Mercurial ได้โดยใช้GpgExtensionส่วนขยายใดที่ถูกแจกจ่ายพร้อมกับ Mercurial คุณไม่สามารถติดแท็กวัตถุที่ไม่ส่งมอบใน Mercurial อย่างที่คุณสามารถทำได้ใน Git แต่นั่นไม่ใช่สิ่งที่สำคัญมากฉันคิดว่า (ที่เก็บ git บางแห่งใช้แท็ก blob เพื่อกระจายคีย์ PGP สาธารณะเพื่อใช้ยืนยันแท็กที่ลงนามแล้ว)

การอ้างอิง: สาขาและแท็ก

ในการอ้างอิง Git (สาขาสาขาและแท็กติดตามระยะไกล) อยู่นอก DAG ของการกระทำ (เท่าที่ควร) การอ้างอิงในrefs/heads/namespace ( สาขาในพื้นที่ ) ชี้ไปที่การกระทำและมักจะมีการปรับปรุงโดย "git กระทำ"; พวกเขาชี้ไปที่ปลาย (หัว) ของสาขานั่นคือเหตุผลที่ชื่อดังกล่าว การอ้างอิงในrefs/remotes/<remotename>/เนมสเปซ ( สาขาการติดตามระยะไกล ) ชี้ไปที่กระทำตามสาขาในที่เก็บระยะไกล<remotename>และได้รับการอัปเดตโดย "git fetch" หรือเทียบเท่า การอ้างอิงในrefs/tags/เนมสเปซ ( แท็ก ) มักจะชี้ไปที่คอมมิท (แท็กน้ำหนักเบา) หรือแท็กออบเจ็กต์ (แท็กที่ใส่หมายเหตุประกอบและลงนาม) และไม่ได้หมายถึงการเปลี่ยนแปลง

แท็ก

ใน Mercurial คุณสามารถให้ชื่อถาวรมีการแก้ไขโดยใช้แท็ก ; แท็กจะถูกจัดเก็บคล้ายกับรูปแบบการเพิกเฉย หมายความว่าแท็กที่มองเห็นได้ทั่วโลกจะถูกเก็บไว้ใน.hgtagsไฟล์ที่มีการควบคุมการแก้ไขในพื้นที่เก็บข้อมูลของคุณ สิ่งนี้มีสองผล: อันดับแรก Mercurial จะต้องใช้กฎพิเศษสำหรับไฟล์นี้เพื่อรับรายการแท็กทั้งหมดและอัปเดตไฟล์ดังกล่าว (เช่นจะอ่านการแก้ไขไฟล์ที่ได้ทำไว้ล่าสุดไม่ได้ตรวจสอบเวอร์ชั่น) สองคุณต้องยอมรับการเปลี่ยนแปลงในไฟล์นี้เพื่อให้แท็กใหม่ปรากฏต่อผู้ใช้รายอื่น / ที่เก็บอื่น ๆ (เท่าที่ฉันเข้าใจ)

Mercurial ยังสนับสนุนแท็กท้องถิ่นที่เก็บไว้hg/localtagsซึ่งไม่สามารถมองเห็นได้โดยผู้อื่น (และแน่นอนไม่สามารถถ่ายโอนได้)

ในแท็ก Git ได้รับการแก้ไข (ค่าคงที่) ชื่อการอ้างอิงไปยังวัตถุอื่น ๆ (โดยปกติคือวัตถุแท็กซึ่งจะถูกเก็บไว้ในrefs/tags/เนมสเปซ ตามค่าเริ่มต้นเมื่อดึงหรือผลักดันชุดการแก้ไข git จะดึงหรือดันแท็กโดยอัตโนมัติซึ่งจะชี้ไปยังการแก้ไขที่ถูกดึงหรือผลัก อย่างไรก็ตามคุณสามารถควบคุมได้บ้างว่าแท็กใดที่ดึงหรือผลักดัน

Git ปฏิบัติแท็กที่มีน้ำหนักเบา (ชี้ไปที่การคอมมิทโดยตรง) และแท็กที่มีคำอธิบายประกอบ (การชี้ไปที่วัตถุแท็กซึ่งมีข้อความแท็กซึ่งรวมถึงลายเซ็น PGP ซึ่งในทางกลับกันที่จะยอมรับ) แตกต่างกันเล็กน้อย กระทำโดยใช้ "git อธิบาย"

Git ไม่มีแท็กท้องถิ่นที่เทียบเท่าใน Mercurial อย่างไรก็ตามแนวทางปฏิบัติที่ดีที่สุดของคอมไพล์แนะนำให้ตั้งค่าพื้นที่เก็บข้อมูลสาธารณะที่แยกต่างหากซึ่งคุณผลักดันการเปลี่ยนแปลงที่พร้อมและจากที่คนอื่นโคลนและดึงข้อมูล ซึ่งหมายความว่าแท็ก (และสาขา) ที่คุณไม่ได้กดเป็นส่วนตัวกับที่เก็บของคุณ บนมืออื่น ๆ คุณยังสามารถใช้ namespace อื่น ๆ กว่าheads, remotesหรือtagsตัวอย่างเช่นlocal-tagsสำหรับแท็กท้องถิ่น

ความเห็นส่วนตัว:ในแท็กความคิดเห็นของฉันควรอยู่นอกกราฟการแก้ไขเนื่องจากมันเป็นสิ่งภายนอก (เป็นตัวชี้ไปยังกราฟการแก้ไข) แท็กควรไม่มีเวอร์ชัน แต่สามารถถ่ายโอนได้ ทางเลือกของ Mercurial ในการใช้กลไกที่คล้ายคลึงกับการละเว้นไฟล์หมายความว่ามันต้องปฏิบัติต่อ.hgtagsเป็นพิเศษ (ไฟล์ในทรีสามารถถ่ายโอนได้ แต่โดยทั่วไปจะเป็นเวอร์ชัน) หรือมีแท็กที่เป็นแบบโลคัลเท่านั้น ( .hg/localtagsไม่ใช่เวอร์ชัน) แต่ไม่สามารถโอนได้)

สาขา

ในสาขาท้องถิ่น Git (ส่วนปลายของสาขาหรือหัวหน้าสาขา) เป็นการอ้างอิงที่มีชื่อถึงการกระทำที่หนึ่งสามารถเติบโตได้ใหม่ สาขายังหมายถึงสายการพัฒนาที่ใช้งานอยู่นั่นคือทั้งหมดที่กระทำสามารถเข้าถึงได้จากปลายสาขา สาขาในพื้นที่นั้นอยู่ในrefs/heads/เนมสเปซดังนั้นเช่นชื่อเต็มของสาขา 'ต้นแบบ' คือ 'refs / heads / master'

สาขาปัจจุบันใน Git (หมายถึงสาขาที่เช็กเอาต์และสาขาที่การส่งมอบใหม่จะดำเนินการ) เป็นสาขาที่อ้างอิงโดยการอ้างอิง HEAD หนึ่งสามารถให้ HEAD ชี้ไปที่การกระทำโดยตรงแทนที่จะเป็นสัญลักษณ์อ้างอิง; สถานการณ์ของการอยู่ในสาขาที่ไม่ระบุชื่อนี้เรียกว่าHEAD HEAD ("สาขา git" แสดงให้เห็นว่าคุณอยู่ใน '(ไม่มีสาขา)')

ใน Mercurial มีสาขาที่ไม่ระบุชื่อ (หัวสาขา) และสามารถใช้บุ๊กมาร์กได้ (ผ่านส่วนขยายบุ๊กมาร์ก ) สาขาบุ๊กมาร์กดังกล่าวล้วน แต่อยู่ในพื้นที่ล้วนๆและชื่อเหล่านั้น (จนถึงเวอร์ชัน 1.6) ไม่สามารถถ่ายโอนได้โดยใช้ Mercurial คุณสามารถใช้ rsync หรือ scp เพื่อคัดลอก.hg/bookmarksไฟล์ไปยังที่เก็บระยะไกล คุณยังสามารถใช้hg id -r <bookmark> <url>เพื่อรับรหัสการแก้ไขของเคล็ดลับปัจจุบันของบุ๊คมาร์ค

ตั้งแต่ 1.6 ที่คั่นหน้าสามารถผลัก / ดึง BookmarksExtensionหน้ามีส่วนในการทำงานกับที่เก็บระยะไกล มีความแตกต่างในการที่ชื่อ Mercurial bookmark เป็นglobalในขณะที่คำจำกัดความของ 'remote' ใน Git อธิบายถึงการแมปชื่อสาขาจากชื่อใน repository ระยะไกลกับชื่อของ Branch-tracking remote ตัวอย่างเช่นrefs/heads/*:refs/remotes/origin/*การทำแผนที่หมายความว่าเราสามารถค้นหาสถานะของ 'master' branch ('refs / heads / master') ใน repository ระยะไกลใน 'origin / master' remote-tracking branch ('refs / remotes / origin / master')

Mercurial ก็มีชื่อเรียกอีกชื่อหนึ่งว่ากิ่งซึ่งฝังอยู่ในคอมมิชชัน (ในเซ็ตการแก้ไข) ชื่อดังกล่าวเป็นสากล (ถ่ายโอนเมื่อดึงข้อมูล) ชื่อสาขาเหล่านั้นจะถูกบันทึกอย่างถาวรเป็นส่วนหนึ่งของเมตาดาต้าเซ็ตการแก้ไข \ u2019s ด้วย Mercurial ที่ทันสมัยคุณสามารถปิด "branch branch" และหยุดการบันทึกชื่อ branch ในกลไกนี้เคล็ดลับของกิ่งไม้จะถูกคำนวณทันที

ในความคิดของฉัน "Mercuryial" ควรได้รับการขนานนามว่าเป็นฉลากแทนเพราะมันคือสิ่งที่พวกเขาเป็น มีสถานการณ์ที่ "สาขาที่มีชื่อ" สามารถมีเคล็ดลับได้หลายอย่าง (หลายลูกที่ไม่มีสัญญา) และยังสามารถประกอบด้วยกราฟที่ไม่ปะติดปะต่อหลายส่วน

ไม่มีอะไรเทียบเท่า Mercurial "กิ่งก้านสาขาที่ฝังตัว" ใน Git; ยิ่งไปกว่านั้นปรัชญาของ Git คือในขณะที่บางคนสามารถพูดได้ว่าสาขานั้นมีการกระทำบางอย่าง แต่ก็ไม่ได้หมายความว่าการกระทำนั้นเป็นของสาขา

โปรดทราบว่าเอกสาร Mercurial ยังเสนอที่จะใช้โคลนแยกต่างหาก (เก็บที่แยกต่างหาก) อย่างน้อยสำหรับสาขายาวอาศัยอยู่ (สาขาเดียวต่อพื้นที่เก็บข้อมูลขั้นตอนการทำงาน) หรือที่รู้จักแตกแขนงจากโคลน

สาขาในการผลักดัน

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

เท่าที่ฉันเข้าใจถ้าคุณผลักช่วงของการแก้ไขที่มีการทำเครื่องหมายว่าอยู่ใน "สาขาที่มีชื่อ" ใน Mercurial parlance คุณจะมี "สาขาที่มีชื่อ" นี้ในที่เก็บที่คุณกดไป ซึ่งหมายความว่าชื่อของสาขาที่ฝัง (เช่นชื่อสาขา) เป็นชื่อโกลบอล (เทียบกับโคลนของพื้นที่เก็บข้อมูล / โครงการที่กำหนด)

ตามค่าเริ่มต้น (ขึ้นอยู่กับpush.defaultตัวแปรการกำหนดค่า) "git push" หรือ "git push < remote >" Git จะผลักดันกิ่งไม้ที่ตรงกันเช่นเฉพาะสาขาในท้องถิ่นที่มีค่าเทียบเท่าที่มีอยู่แล้วในที่เก็บระยะไกลที่คุณกด คุณสามารถใช้--allตัวเลือกในการ git-push ("git push - all ") เพื่อกดทุกสาขาคุณสามารถใช้ "git push < remote > < branch >" เพื่อกดสาขาเดียวที่กำหนดและคุณสามารถใช้ "git push < ระยะไกล > HEAD" ที่จะผลักดันสาขาในปัจจุบัน

จากทั้งหมดที่กล่าวมาข้างต้นถือว่า Git ไม่ได้กำหนดค่าที่จะผลักดันผ่านremote.<remotename>.push ตัวแปรการกำหนดค่า

สาขาในการดึง

หมายเหตุ:ที่นี่ฉันใช้คำศัพท์ Git โดยที่ "การดึงข้อมูล" หมายถึงการดาวน์โหลดการเปลี่ยนแปลงจากที่เก็บระยะไกลโดยไม่ต้องรวมการเปลี่ยนแปลงเหล่านั้นกับงานในท้องถิ่น นี่คือสิ่งที่ " git fetch" และ " hg pull" ทำ

ถ้าผมเข้าใจอย่างถูกต้องตามค่าเริ่มต้น Mercurial เรียกทุกหัวจากพื้นที่เก็บข้อมูลระยะไกล แต่คุณสามารถระบุสาขาสามารถดึงข้อมูลผ่านทาง " hg pull --rev <rev> <url>" หรือ " hg pull <url>#<rev>" เพื่อให้ได้สาขาเดียว คุณสามารถระบุ <rev> โดยใช้ตัวระบุการแก้ไขชื่อ "named branch" (branch ที่ฝังใน changelog) หรือชื่อบุ๊กมาร์ก ชื่อบุ๊กมาร์ก (อย่างน้อยปัจจุบัน) ไม่ได้รับการถ่ายโอน การแก้ไข "สาขาที่มีชื่อ" ทั้งหมดที่คุณได้รับจะถูกโอนไป "hg pull" เก็บเคล็ดลับของสาขาที่ดึงมาเป็นแบบไม่ระบุชื่อและไม่มีชื่อ

ใน Git โดยค่าเริ่มต้น (สำหรับรีโมต 'ต้นทาง' สร้างโดย "git clone" และสำหรับรีโมตที่สร้างโดยใช้ "git remote add") " git fetch" (หรือ " git fetch <remote>") รับสาขาทั้งหมดจากที่เก็บระยะไกล (จากrefs/heads/เนมสเปซ) และเก็บไว้ในrefs/remotes/namespace ซึ่งหมายความว่าตัวอย่างเช่นสาขาที่ชื่อ 'master' (ชื่อเต็ม: 'refs / heads / master') ใน 'แหล่งกำเนิด' ระยะไกล 'จะถูกเก็บไว้ (บันทึก) เป็น' แหล่งกำเนิด / ต้นแบบ ' สาขาติดตามระยะไกล (ชื่อเต็ม:' refs / รีโมท / กำเนิด / โท)

คุณสามารถดึงข้อมูลสาขาเดียวใน Git ได้โดยใช้git fetch <remote> <branch>- Git จะเก็บสาขาที่ร้องขอใน FETCH_HEAD ซึ่งเป็นสิ่งที่คล้ายกับ Mercurial heads ที่ไม่มีชื่อ

สิ่งเหล่านี้เป็นเพียงตัวอย่างของกรณีเริ่มต้นของไวยากรณ์ Git refspec ที่มีประสิทธิภาพ: ด้วย refspecs คุณสามารถระบุและ / หรือกำหนดค่าว่าสาขาใดที่ต้องการดึงข้อมูลและสถานที่จัดเก็บ ตัวอย่างเช่นค่าเริ่มต้น "ดึงทุกสาขา" จะแสดงด้วย '+ refs / heads / *: refs / remotes / origin / *' wildcard refspec และ "fetch single branch" นั้นย่อมาจาก 'refs / heads / <branch>:' . Refspecs ใช้เพื่อแม็พชื่อของ branch (refs) ในที่เก็บรีโมตกับชื่อ refs ท้องถิ่น แต่คุณไม่จำเป็นต้องรู้ (มาก) เกี่ยวกับ refspec เพื่อให้สามารถทำงานได้อย่างมีประสิทธิภาพกับ Git (ขอบคุณคำสั่ง "git remote" เป็นหลัก)

ความเห็นส่วนตัว:ส่วนตัวแล้วฉันคิดว่า "การตั้งชื่อสาขา" (ด้วยชื่อสาขาที่ฝังอยู่ในเมตาดาต้าเซ็ตการแก้ไข) ใน Mercurial นั้นเป็นการออกแบบที่เข้าใจผิดกับเนมสเปซทั่วโลกโดยเฉพาะอย่างยิ่งสำหรับระบบควบคุมเวอร์ชันกระจาย ตัวอย่างเช่นลองดูว่าทั้ง Alice และ Bob มี "branch branch" ชื่อ 'for-joe' ในที่เก็บของพวกเขาสาขาที่ไม่มีอะไรเหมือนกัน ในพื้นที่เก็บข้อมูลของโจ แต่ทั้งสองสาขาจะถูกทำร้ายเป็นสาขาเดียว ดังนั้นคุณจะมีวิธีป้องกันอนุสัญญาชื่อสาขา นี่ไม่ใช่ปัญหาของ Git ซึ่งในที่เก็บของโจสาขา 'for-joe' จากอลิซจะเป็น 'alice / for-joe' และจาก Bob มันจะเป็น 'bob / for-joe'

"สาขาบุ๊กมาร์ก" ของ Mercurial ในปัจจุบันขาดกลไกการกระจายในแกน

ความแตกต่าง:
พื้นที่นี้เป็นหนึ่งในความแตกต่างที่สำคัญระหว่าง Mercurial และ Git ขณะที่James woodyattและSteve Loshกล่าวในคำตอบของพวกเขา โดยค่าเริ่มต้น Mercurial ใช้ codelines ที่ไม่ระบุชื่อเบาซึ่งในคำศัพท์เรียกว่า "หัว" Git ใช้กิ่งไม้ที่มีน้ำหนักเบาพร้อมการแมปแบบหัวฉีดเพื่อแมปชื่อสาขาในที่เก็บระยะไกลกับชื่อของสาขาการติดตามระยะไกล Git "บังคับ" ให้คุณตั้งชื่อกิ่ง (ดียกเว้นสาขาที่ไม่มีชื่อเดียวสถานการณ์ที่เรียกว่า HEAD HEAD) แต่ฉันคิดว่าวิธีนี้จะทำงานได้ดีขึ้นด้วยเวิร์กโฟลว์สาขาที่หนักเช่นเวิร์กโฟลว์สาขาหัวข้อซึ่งหมายถึงหลายสาขาในกระบวนทัศน์พื้นที่เก็บข้อมูลเดียว

การแก้ไขการตั้งชื่อ

ใน Git มีหลายวิธีในการตั้งชื่อการแก้ไข (อธิบายเช่นในgit rev-parse manpage):

  • ชื่อวัตถุ SHA1 แบบเต็ม (สตริงเลขฐานสิบหก 40- ไบต์) หรือสตริงย่อยที่ไม่ซ้ำกันภายในที่เก็บ
  • ชื่ออ้างอิงสัญลักษณ์เช่น 'master' (หมายถึงสาขา 'master') หรือ 'v1.5.0' (หมายถึงแท็ก) หรือ 'origin / next' (อ้างอิงสาขาติดตามระยะไกล)
  • ส่วนต่อท้าย^เพื่อแก้ไขพารามิเตอร์หมายถึงผู้ปกครองแรกของวัตถุกระทำ^nหมายถึงผู้ปกครองที่ n ของการผสานกระทำ ส่วนต่อท้าย~nไปยังพารามิเตอร์การแก้ไขหมายถึงบรรพบุรุษของ n-th ของการกระทำในสายพ่อแม่แรกตรง คำต่อท้ายเหล่านั้นสามารถนำมารวมกันเพื่อสร้างตัวระบุการแก้ไขต่อไปนี้เส้นทางจากการอ้างอิงสัญลักษณ์เช่น 'pu ~ 3 ^ 2 ~ 3'
  • เอาท์พุทของ "git อธิบาย" คือแท็กที่ใกล้เคียงที่สุดเลือกตามด้วยเครื่องหมายขีดกลางและจำนวนของการกระทำตามด้วยเครื่องหมายขีดกลาง 'g' และชื่อวัตถุย่อตัวอย่างเช่น 'v1.6.5.1-75- g5bf8097'

นอกจากนี้ยังมีตัวระบุการแก้ไขที่เกี่ยวข้องกับ reflog ไม่ได้กล่าวถึงที่นี่ ใน Git แต่ละวัตถุไม่ว่าจะกระทำแท็กต้นไม้หรือหยดมีตัวระบุ SHA-1 มีไวยากรณ์พิเศษเช่น 'next: Documentation' หรือ 'next: README' เพื่ออ้างถึง tree (directory) หรือ blob (เนื้อหาไฟล์) ตามการแก้ไขที่ระบุ

Mercurial มีหลายวิธีในการตั้งชื่อเซ็ตการแก้ไข (อธิบายเช่นในhg manpage):

  • จำนวนเต็มธรรมดาจะถือว่าเป็นหมายเลขการแก้ไข หนึ่งต้องจำไว้ว่าตัวเลขการแก้ไขที่มีในท้องถิ่นเพื่อให้พื้นที่เก็บข้อมูล ; ในพื้นที่เก็บข้อมูลอื่น ๆ พวกเขาอาจแตกต่างกัน
  • จำนวนเต็มลบจะถือเป็นออฟเซ็ตตามลำดับจากปลายด้วย -1 แสดงถึงเคล็ดลับ -2 แสดงถึงการแก้ไขก่อนหน้าเคล็ดลับและอื่น ๆ พวกเขายังท้องถิ่นเพื่อพื้นที่เก็บข้อมูล
  • ตัวระบุการแก้ไขที่ไม่ซ้ำกัน (สตริงเลขฐานสิบหก 40 หลัก) หรือคำนำหน้าเฉพาะ
  • ชื่อแท็ก (ชื่อสัญลักษณ์ที่เชื่อมโยงกับการแก้ไขที่กำหนด) หรือชื่อบุ๊กมาร์ก (พร้อมส่วนขยาย: ชื่อสัญลักษณ์ที่เชื่อมโยงกับส่วนหัวที่กำหนดพื้นที่ในพื้นที่เก็บข้อมูล) หรือ "branch branch" (กระทำ label; ทิป (การกระทำที่ไม่มีลูก) ของการกระทำทั้งหมดที่มีป้ายกำกับการส่งมอบที่มีหมายเลขการแก้ไขที่ใหญ่ที่สุดหากมีมากกว่าหนึ่งเคล็ดลับดังกล่าว)
  • ชื่อ "เคล็ดลับ" ที่สงวนไว้เป็นแท็กพิเศษที่ระบุการแก้ไขล่าสุดเสมอ
  • ชื่อสงวน "null" หมายถึงการแก้ไขว่าง
  • ชื่อที่สงวนไว้ "." บ่งบอกถึงไดเรกทอรีไดเรกทอรีการทำงาน

ความแตกต่างดัง
ที่คุณเห็นการเปรียบเทียบรายการด้านบน Mercurial เสนอหมายเลขการแก้ไขท้องถิ่นกับที่เก็บในขณะที่ Git ไม่มี ในทางกลับกัน Mercurial เสนอการชดเชยแบบสัมพัทธ์เฉพาะจาก 'เคล็ดลับ' (สาขาปัจจุบัน) ซึ่งอยู่ในพื้นที่เก็บข้อมูล (อย่างน้อยไม่มีParentrevspecExtension ) ในขณะที่ Git อนุญาตให้ระบุการกระทำใด ๆ ต่อไปนี้จากเคล็ดลับใด ๆ

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

ดูเพิ่มเติมที่: บทความตัวแก้ไขการแก้ไขประเภทต่าง ๆ มากมายบนบล็อกของ Elijah (ของใหม่)

ความเห็นส่วนตัว:ฉันคิดว่าตัวเลขการแก้ไขมีการประเมินค่ามากเกินไป (อย่างน้อยสำหรับการพัฒนาแบบกระจายและ / หรือประวัติที่ไม่เป็นเชิงเส้น / แตกกิ่ง) ขั้นแรกสำหรับระบบควบคุมเวอร์ชันแบบกระจายพวกเขาต้องเป็นแบบโลคัลไปยังที่เก็บหรือต้องการการจัดการที่เก็บบางส่วนในวิธีพิเศษในฐานะหน่วยงานการกำหนดหมายเลขกลาง ประการที่สองโครงการขนาดใหญ่ที่มีประวัติยาวนานขึ้นสามารถมีจำนวนการแก้ไขในช่วง 5 หลักดังนั้นจึงมีข้อได้เปรียบเล็กน้อยเพียงเล็กน้อยเมื่อเทียบกับตัวระบุการแก้ไขสั้น ๆ ถึง 6-7 ตัวอักษรและบ่งบอกถึงการสั่งซื้อที่เข้มงวดในขณะที่ การแก้ไข n และ n + 1 ไม่จำเป็นต้องเป็น parent และ child)

ช่วงการแก้ไข

ในช่วงการแก้ไข Git เป็นทอพอโลยี ปกติเห็นA..Bไวยากรณ์ซึ่งสำหรับการเชิงเส้นประวัติศาสตร์หมายถึงช่วงการแก้ไขเริ่มต้นที่ A ( แต่ไม่รวม A) และสิ้นสุดที่ B (ช่วงคือคือเปิดจากด้านล่าง ) เป็นชวเลข ( "น้ำตาลประโยค") สำหรับ^A Bซึ่งสำหรับประวัติคำสั่ง traversing หมายถึงทั้งหมด กระทำการที่สามารถเข้าถึงได้จาก B ยกเว้นสิ่งที่สามารถเข้าถึงได้จาก A. ซึ่งหมายความว่าพฤติกรรมของA..Bช่วงนั้นสามารถคาดเดาได้ทั้งหมด (และค่อนข้างมีประโยชน์) แม้ว่า A จะไม่ใช่บรรพบุรุษของ B: A..Bหมายถึงช่วงของการแก้ไขจากบรรพบุรุษร่วมของ A และ B ) เพื่อแก้ไข B.

ในช่วง Mercurial แก้ไขจะขึ้นอยู่กับช่วงของตัวเลขการแก้ไข ช่วงที่มีการระบุโดยใช้A:Bไวยากรณ์และขัดกับช่วง Git ทำหน้าที่เป็นช่วงเวลาปิด นอกจากนี้ช่วง B: A คือช่วง A: B ในลำดับย้อนกลับซึ่งไม่ได้เป็นกรณีใน Git (แต่ดูด้านล่างทราบเกี่ยวกับA...Bไวยากรณ์) แต่ความเรียบง่ายดังกล่าวมาพร้อมกับราคา: ช่วงการแก้ไข A: B เหมาะสมถ้าหาก A เป็นบรรพบุรุษของ B หรือในทางกลับกันเช่นมีประวัติเชิงเส้น มิฉะนั้น (ฉันเดาว่า) ช่วงนั้นไม่สามารถคาดเดาได้และผลลัพธ์จะอยู่ในพื้นที่เก็บข้อมูล (เนื่องจากหมายเลขการแก้ไขนั้นอยู่ในพื้นที่เก็บข้อมูล)

สิ่งนี้ได้รับการแก้ไขด้วย Mercurial 1.6 ซึ่งมีช่วงการแก้ไขใหม่ของโทโพโลยีที่เข้าใจว่า 'A .. B' (หรือ 'A :: B') เป็นชุดการเปลี่ยนแปลงที่เป็นทั้งลูกหลานของ X และบรรพบุรุษของ Y นี่คือ ฉันเดาว่าเทียบเท่ากับ '--ancestry-path A..B' ใน Git

Git ยังมีสัญลักษณ์A...Bสำหรับความแตกต่างที่สมมาตรของการแก้ไข; มันหมายถึงA B --not $(git merge-base A B)ซึ่งหมายความว่าทุกคนสามารถเข้าถึงได้จาก A หรือ B แต่ไม่รวมถึงการกระทำทั้งหมดที่สามารถเข้าถึงได้จากทั้งสอง (เข้าถึงได้จากบรรพบุรุษร่วมกัน)

เปลี่ยนชื่อ

Mercurial ใช้การติดตามการเปลี่ยนชื่อเพื่อจัดการกับการเปลี่ยนชื่อไฟล์ ซึ่งหมายความว่าข้อมูลเกี่ยวกับความจริงที่ว่าไฟล์ถูกเปลี่ยนชื่อจะถูกบันทึกในเวลากระทำ; ใน Mercurial ข้อมูลนี้จะถูกบันทึกในฟอร์ม "Enhanced diff" ในเมตาดาต้าfilelog (ไฟล์ revlog) ผลของสิ่งนี้คือคุณต้องใช้hg rename/ hg mv... หรือคุณต้องจำไว้ว่าhg addremoveให้ทำการตรวจจับการเปลี่ยนชื่อตามความคล้ายคลึงกัน

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

ทั้ง Git และ Mercurial จำเป็นต้องใช้--followตัวเลือกในการติดตามการเปลี่ยนชื่อเมื่อแสดงประวัติของไฟล์เดียว ทั้งสองสามารถทำตามการเปลี่ยนชื่อเมื่อแสดงประวัติศาสตร์บรรทัดที่ชาญฉลาดของไฟล์ใน/git blamehg annotate

ใน Git git blameคำสั่งสามารถติดตามการเคลื่อนไหวของโค้ดย้ายรหัส (หรือคัดลอก) จากไฟล์หนึ่งไปยังอีกไฟล์แม้ว่าการเคลื่อนไหวของรหัสไม่ได้เป็นส่วนหนึ่งของการเปลี่ยนชื่อไฟล์ที่เป็นประโยชน์ เท่าที่ฉันรู้ว่าคุณสมบัตินี้เป็นเอกลักษณ์ของ Git (ในขณะที่เขียนตุลาคม 2009)

โปรโตคอลเครือข่าย

ทั้ง Mercurial และ Git มีการรองรับการดึงและผลักดันไปยังที่เก็บบนระบบไฟล์เดียวกันโดยที่ URL ที่เก็บเป็นเพียงเส้นทางของระบบไฟล์ไปยังที่เก็บ ทั้งยังรองรับการดึงข้อมูลจากไฟล์บันเดิ

การสนับสนุน Mercurial การดึงและผลักดันผ่าน SSH และผ่านโปรโตคอล HTTP สำหรับ SSH ต้องมีบัญชีเชลล์ที่สามารถเข้าถึงได้บนเครื่องปลายทางและสำเนาของ hg ที่ติดตั้ง / พร้อมใช้งาน สำหรับการเข้าถึง HTTP hg-serveจำเป็นต้องใช้สคริปต์รันหรือ Mercurial CGI และจำเป็นต้องติดตั้ง Mercurial บนเครื่องเซิร์ฟเวอร์

Git รองรับโปรโตคอลสองชนิดที่ใช้ในการเข้าถึงที่เก็บระยะไกล:

  • โปรโตคอล "สมาร์ท"ซึ่งรวมถึงการเข้าถึงผ่าน SSH และผ่าน git: // โพรโทคอลที่กำหนดเอง (โดยgit-daemon) ต้องมีการติดตั้ง git บนเซิร์ฟเวอร์ การแลกเปลี่ยนในโปรโตคอลเหล่านั้นประกอบด้วยไคลเอนต์และเซิร์ฟเวอร์เจรจาเกี่ยวกับวัตถุใดที่พวกเขามีเหมือนกันจากนั้นสร้างและส่ง packfile Modern Git มีการรองรับโปรโตคอล HTTP "smart"
  • โปรโตคอล "โง่"ซึ่งรวมถึง HTTP และ FTP (เฉพาะสำหรับการเรียก) และ HTTPS (สำหรับการผลักดันผ่าน WebDAV) ไม่จำเป็นต้องคอมไพล์ติดตั้งบนเซิร์ฟเวอร์ แต่พวกเขาจะต้องใช้พื้นที่เก็บข้อมูลที่มีข้อมูลพิเศษที่สร้างขึ้นโดยgit update-server-info(มักจะวิ่งออกจากเบ็ด ) การแลกเปลี่ยนประกอบด้วยไคลเอนต์ที่เดินผ่านเชนส่งมอบและดาวน์โหลดวัตถุหลวมและไฟล์แพ็คตามต้องการ ข้อเสียคือมันดาวน์โหลดมากกว่าที่ต้องการอย่างเคร่งครัด (เช่นในมุมที่มีไฟล์แพ็คเพียงไฟล์เดียวมันจะดาวน์โหลดทั้งหมดแม้เมื่อดึงไฟล์เพียงไม่กี่ครั้งเท่านั้น) และต้องใช้การเชื่อมต่อหลายอย่างเพื่อให้เสร็จสิ้น

ขยาย: scriptability vs extensions (ปลั๊กอิน)

Mercurial มีการนำมาใช้ในPythonโดยมีคอร์โค้ดบางตัวที่เขียนด้วย C เพื่อประสิทธิภาพ มันมี API สำหรับการเขียนส่วนขยาย (ปลั๊กอิน) เป็นวิธีการเพิ่มคุณสมบัติพิเศษ ฟังก์ชั่นบางอย่างเช่น "สาขาบุ๊กมาร์ก" หรือการแก้ไขการเซ็นชื่อมีให้ในส่วนขยายที่กระจายด้วย Mercurial และต้องเปิดใช้งาน

Git จะดำเนินการในC , Perlและเชลล์สคริปต์ Git มีคำสั่งระดับต่ำจำนวนมาก ( ระบบประปา ) ที่เหมาะสมสำหรับใช้ในสคริปต์ ทางปกติของการแนะนำคุณสมบัติใหม่คือการเขียนเป็น Perl หรือเชลล์สคริปต์และเมื่อส่วนติดต่อผู้ใช้รักษาเขียนมันใน C สำหรับประสิทธิภาพการพกพาและในกรณีของเชลล์สคริปต์หลีกเลี่ยงกรณีมุม (ขั้นตอนนี้จะเรียกว่าbuiltinification )

Git อาศัยและสร้างขึ้นในรูปแบบ [พื้นที่เก็บข้อมูล] และ [เครือข่าย] โปรโตคอล แทนที่จะใช้การผูกภาษามีการใช้ Git (บางส่วนหรือทั้งหมด) ในภาษาอื่น (บางส่วนเป็นการนำไปใช้ใหม่บางส่วนและบางส่วนล้อมรอบคำสั่ง git): JGit (Java ใช้โดย EGit, Eclipse Git Plugin), Grit (Ruby) , Dulwich (Python), git # (C #)


TL; DR


32
สิ่งที่สามารถเพิ่มได้คือ hg พยายามอย่างหนักที่จะกีดกันการเขียนประวัติใหม่ (สามารถทำได้กับส่วนขยายเท่านั้น: mq, histedit, rebase) ในขณะที่ git ทำนอกกรอบ (และดูเหมือนว่าเป็นส่วนหนึ่งของชุมชน แม้จะกระตุ้นให้มัน)
tonfa

80
ฉันคิดว่า "ประวัติการเขียนใหม่" นั้นทำให้เกิดเสียงที่ไม่จำเป็น สิ่งที่ฉันส่งเสริมในคอมไพล์คือผู้คนพิจารณาประวัติที่พวกเขาเผยแพร่ คนอื่นต้องบริโภคประวัติศาสตร์นั้น ไม่มีใคร (ไม่ใช่แม้กระทั่งคุณ) ให้ความสนใจในการกระทำ "โอ๊ะโอ, ลืมไฟล์" ของคุณ ไม่มีใครสนใจชุดของการรวมขาเข้าที่คุณทำในขณะที่คุณกำลังติดตามสาขาต้นน้ำในขณะที่ทำงานกับคุณลักษณะใหม่ สิ่งประเภทนั้นทำให้ประวัติศาสตร์ (และเครื่องมือที่เกี่ยวข้อง) เข้าใจยากและไม่มีคุณค่า
ดัสติน

5
@Jakub: กิ่งที่มีชื่อเป็นสิ่งที่ไม่มีอยู่ในคอมไพล์ มันเป็นเพียงฟิลด์ในคำอธิบาย cset (และนั่นเป็นส่วนหนึ่งของประวัติศาสตร์ดังนั้นมันจึงไม่เปลี่ยนรูปเว้นแต่คุณเปลี่ยนแฮช ฯลฯ ) บางอย่างเช่นกิ่งก้านสาขาเป็นที่คั่นหน้า ("ชื่อหัว") แต่ในปัจจุบันยังไม่สามารถถ่ายโอนจากระยะไกลได้ stevelosh.com/blog/entry/2009/8/30/…อธิบายได้ดีมาก
tonfa

28
"เดิม Mercurial สนับสนุนเพียงหนึ่งสาขาต่อหนึ่งเวิร์กโฟลว์ของที่เก็บเท่านั้นและจะแสดงขึ้นมา" เอ่อไม่ Mercurial ไม่ได้สนับสนุนสาขาที่มีชื่อแต่คุณสามารถมีสาขาที่ไม่ระบุชื่อได้มากเท่าที่คุณต้องการใน repo เดียว ตัดกันด้วยคอมไพล์ซึ่งทำให้การไม่ระบุตัวตนทำให้เกิดความเจ็บปวดอย่างมาก คุณต้องนึกถึงชื่อของสาขาเล็ก ๆ ทุกแห่งถ้าคุณต้องการทำสิ่งต่าง ๆ (และหลีกเลี่ยงการเก็บขยะในที่ทำงาน)
Steve Losh

17
@SteveLosh: คุณคิดว่าการมีสาขาที่ไม่ระบุชื่อจำนวนมากใน Mercurial เป็นสิ่งที่ดี แต่สำหรับฉันมันดูน่ากลัว คุณจะแยกพวกเขาออกจากกันได้อย่างไร? และคุณคิดว่าการตั้งชื่อสาขาใน Git นั้นยากมาก แต่ถ้าคุณมีจุดประสงค์ในการสร้างสาขาคุณก็จะมีชื่อพร้อมใช้ หากคุณไม่มีจุดประสงค์ก็อย่าแยกสาขา ฉันไม่เห็นว่า Mercurial มอบประโยชน์ใด ๆ ให้กับที่นี่ ฉันเห็นเพียงความเจ็บปวดและความสับสน
iconoclast

57

ฉันคิดว่าคุณสามารถรับรู้ได้ว่าระบบเหล่านั้นมีความคล้ายคลึงกันหรือแตกต่างกันอย่างไรโดยใช้วิดีโอทั้งสองนี้:

Linus Torvalds บน Git ( http://www.youtube.com/watch?v=4XpnKHJAok8 )
Bryan O'Sullivan บน Mercurial ( http://www.youtube.com/watch?v=JExtkqzEoHY )

ทั้งสองมีความคล้ายคลึงกันในการออกแบบ แต่แตกต่างกันมากในการใช้งาน

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

พวกเขายังบอกว่าคอมไพล์ช้ากว่า HTTP แต่มันมีโปรโตคอลเครือข่ายและเซิร์ฟเวอร์ของตัวเอง

Git ทำงานได้ดีขึ้นในฐานะลูกค้าหนา SVN กว่า Mercurial คุณสามารถดึงและดันกับเซิร์ฟเวอร์ SVN ฟังก์ชั่นนี้ยังอยู่ระหว่างการพัฒนาใน Mercurial

ทั้ง Mercurial และ Git มีโซลูชั่นการโฮสต์เว็บที่ดีมาก (BitBucket และ GitHub) แต่ Google Code รองรับ Mercurial เท่านั้น โดยวิธีการที่พวกเขามีการเปรียบเทียบรายละเอียดมาก Mercurial และ Git ที่พวกเขาสำหรับการตัดสินใจที่หนึ่งที่จะสนับสนุน ( http://code.google.com/p/support/wiki/DVCSAnalysis ) มันมีข้อมูลที่ดีมากมาย


8
ฉันขอแนะนำให้อ่านความคิดเห็นทั้งหมดในหน้ารหัส Google ข้อมูลรู้สึกค่อนข้างลำเอียงและไม่ตรงกับประสบการณ์ของฉัน ฉันชอบ hg และใช้มันอย่างกว้างขวางเป็นเวลาหนึ่งปีหรือมากกว่านั้น ตอนนี้ฉันใช้คอมไพล์โดยเฉพาะ มีสิ่งที่ฉันต้องทำให้สำเร็จที่คอมไพล์ทำได้ง่ายและ hg ทำให้แทบเป็นไปไม่ได้ (แม้ว่าบางคนชอบที่จะเรียกสิ่งนี้โดยใช้ "ภาวะแทรกซ้อน") คอมไพล์พื้นฐานนั้นง่ายเหมือนเบส hg
ดัสติน

11
ดัสตินอาจแสดงบางกรณี "คอมไพล์ง่าย hg ไม่มาก"?
Gregg Lind

1
@ knittl ไม่เลย สาเหตุหลักมาจากการที่พวกเขาใช้งานได้ยากเนื่องจาก git ขาดโปรโตคอล http อัจฉริยะ (ส่วนหน้าของ Google ส่วนใหญ่ใช้ http)
tonfa

2
@tonfa: โปรโตคอล HTTP อัจฉริยะสำหรับ Git กำลังได้รับการพัฒนา (เช่น: มีแพตช์ในรายชื่อผู้รับจดหมาย git และอยู่ใน 'pu' = สาขาการปรับปรุงที่เสนอในที่เก็บ git.git)
Jakub Narębski

4
ณ ตอนนี้ Google Code รองรับ Git ด้วย
Andrej Kirejeŭ

30

ฉันเขียนรายการบล็อกเกี่ยวกับโมเดลการแตกแขนงของ Mercurial เมื่อไม่นานมานี้และรวมถึงการเปรียบเทียบกับโมเดลการแตกแขนงของคอมไพล์ คุณอาจจะพบว่ามันน่าสนใจ: http://stevelosh.com/blog/entry/2009/8/30/a-guide-to-branching-in-mercurial/


@Steve Losh: ฉันต้องการที่จะแสดงความคิดเห็นเกี่ยวกับรายการบล็อกนี้ (เกี่ยวกับสาขาที่ไม่มีชื่อหรือที่รู้จักกันว่า HEAD ซึ่งเป็นหัวหน้าเดี่ยวและเกี่ยวกับ git-fetch กำลังดึงสาขาทั้งหมดไม่ใช่หนึ่ง) แต่ฉันได้รับข้อผิดพลาด 500 เซิร์ฟเวอร์
Jakub Narębski

1
@Jakub Narębskiฉันพนันได้เลยว่าปัญหาคือตัวละครที่ไม่ใช่ ASCII ในชื่อของคุณ ฉันค่อนข้างแน่ใจว่าฉันพบปัญหาเดียวกันในเว็บไซต์อื่นและปรากฎว่า Python Askimet เชื่อมโยงกับโช้คบน Unicode ฉันจะดู
Steve Losh

@ Steve Losh: ขอบคุณสำหรับข้อมูลหลังจาก "unidecoding" ชื่อของฉันฉันสามารถโพสต์ความคิดเห็นได้ คำอธิบายที่ดีมากเกี่ยวกับการแตกแขนงใน Mercurial (แต่ฉันก็ยังคิดว่ามันด้อยกว่า ;-))
Jakub Narębski

@SteveLosh ฉันขอแนะนำให้คุณขยายคำตอบนี้เพื่อให้การตรวจสอบ Mercurial สมบูรณ์ยิ่งขึ้น ตอนนี้คำตอบยอดนิยมน่าเสียดายที่โฆษณาสำหรับคอมไพล์ส่วนใหญ่เป็นเพราะผู้เขียนไม่ได้ใช้ Mercurial อย่างกว้างขวางและไม่เข้าใจวิธีใช้อย่างมีประสิทธิภาพ มันจะดีสำหรับคำตอบอื่นเพื่อให้มุมมองของ mercurial ดังนั้นพูด
Warren Dew

25

ฉันใช้ทั้งสองค่อนข้างสม่ำเสมอ ความแตกต่างของการทำงานที่สำคัญคือวิธีที่ Git และ Mercurial ตั้งชื่อสาขาในที่เก็บ ด้วย Mercurial ชื่อสาขาจะถูกโคลนและดึงออกมาพร้อมกับเซ็ตการแก้ไข เมื่อคุณเพิ่มการเปลี่ยนแปลงไปยังสาขาใหม่ใน Mercurial และกดไปที่ที่เก็บอื่นชื่อสาขาจะถูกพุชในเวลาเดียวกัน ดังนั้นชื่อสาขาจะมีทั่วโลกมากขึ้นหรือน้อยลงใน Mercurial และคุณต้องใช้ส่วนขยายของคั่นหน้าเพื่อให้มีชื่อชื่อเฉพาะที่มีน้ำหนักเบาในท้องถิ่น เรียกว่า "หัว") ใน Git ชื่อสาขาและการแมปแบบแทรกเข้าไปยังสาขาระยะไกลจะถูกจัดเก็บไว้ในเครื่องและคุณต้องจัดการอย่างชัดเจนซึ่งหมายถึงการรู้วิธีการทำเช่นนั้น

ตามที่คนอื่นจะทราบที่นี่มีความแตกต่างเล็กน้อยมากมาย สิ่งที่มีกิ่งก้านสาขานั้นต่างจากที่อื่น


2
ดูโพสต์นี้สำหรับคำอธิบายที่ดีเกี่ยวกับสี่สาขาใน Mercurial: stevelosh.com/blog/entry/2009/8/30/…
Martin Geisler


11

Mercurial เขียนด้วยไพ ธ อนเกือบทั้งหมด แกนกลางของ Git เขียนด้วย C (และควรเร็วกว่า Mercurial's) และเครื่องมือที่เขียนด้วย sh, perl, tcl และใช้อุปกรณ์มาตรฐานของ GNU ดังนั้นจึงจำเป็นต้องนำอุปกรณ์และล่ามทั้งหมดเหล่านี้ไปไว้ในระบบที่ไม่มีสิ่งเหล่านั้น (เช่น Windows)

การสนับสนุนทั้งสองทำงานร่วมกับ SVN ได้แม้ว่าการสนับสนุน AFAIK svn จะใช้งานไม่ได้สำหรับ git บน Windows (อาจเป็นเพราะฉันโชคไม่ดี / อ่อนแอใครจะรู้) นอกจากนี้ยังมีส่วนขยายที่อนุญาตให้ทำงานร่วมกันระหว่าง git และ Mercurial

Mercurial มีการรวม Visual Studio ที่ดี ครั้งล่าสุดที่ฉันตรวจสอบปลั๊กอินสำหรับ Gitทำงานได้ช้ามาก

ชุดคำสั่งพื้นฐานมีลักษณะคล้ายกันมาก (init, clone, add, status, commit, push, pull, etc. ) ดังนั้นเวิร์กโฟลว์พื้นฐานจะเหมือนกัน นอกจากนี้ยังมีไคลเอนต์ที่เหมือน TortoiseSVN สำหรับทั้งคู่

ส่วนขยายสำหรับ Mercurial สามารถเขียนเป็นไพ ธ อน (ไม่ต้องแปลกใจ!) และสำหรับคอมไพล์พวกเขาสามารถเขียนในรูปแบบที่สามารถปฏิบัติการได้ (ไบนารี่แบบไบนารี, เชลล์สคริปต์เป็นต้น) git bisectส่วนขยายบางบ้าที่มีประสิทธิภาพเช่น


9
Mercurial core เขียนใน C ด้วย FYI (แต่อาจเป็นแกนที่เล็กกว่า git)
tonfa

1
ฉันใช้ git-svn บน Windows โดยไม่มีปัญหา ที่ใช้ Cygwin (เพียงขวาวิธีที่จะใช้คอมไพล์บน Windows ถ้าคุณถามฉัน) ไม่สามารถพูดหา msysgit ได้
Dan Molding

@Dan Molding: ใช่ฉันเคยประสบปัญหากับ msysgit อาจต้องลองพอร์ต cygwin (ฉันเคยมีประสบการณ์การใช้ cygwin มาก่อนดังนั้นฉันจึงหลีกเลี่ยง) ขอบคุณสำหรับคำแนะนำ!
elder_george

ฉันเองไม่ชอบการบุกรุกของ cygwin ในรีจิสทรีเพื่อเก็บข้อมูลผู้ใช้ มันเป็น PITA ที่จะให้มันปิดคีย์ USB และทำสำเนาการคัดลอกไดรฟ์ c: \ ไว้ในเครื่องเมื่อฉันต้องการเรียกใช้เร็วกว่าที่คีย์ USB ของฉันสามารถทำได้ : - /
Chris K

1
ฉันใช้ปลั๊กอิน Git สำหรับ Visual Studio ที่กล่าวถึงข้างต้นและประสิทธิภาพของรุ่นปัจจุบันนั้นดี มันใช้เครื่องมือบรรทัดคำสั่งเพื่อทำงานดังนั้นฉันไม่คิดว่ามันจะลดประสิทธิภาพลงอย่างมากในโครงการขนาดใหญ่
Stuart Ellis

11

หากคุณต้องการการสนับสนุน Windows ที่ดีคุณอาจชอบ Mercurial TortoiseHg (ปลั๊กอิน Windows explorer) จัดการเพื่อเสนอส่วนต่อประสานกราฟิกที่ใช้งานง่ายกับเครื่องมือที่ค่อนข้างซับซ้อน ในฐานะที่เป็นรัฐที่นี่คุณยังจะมีปลั๊กอิน Visual Studio อย่างไรก็ตามครั้งล่าสุดที่ฉันลองส่วนติดต่อ SVN นั้นใช้งานไม่ได้กับ Windows

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


นอกจากนี้ยังมี TortoiseGit หากคุณไม่ต้องการใช้บรรทัดคำสั่ง ( แต่ต้อง msysgit ที่จะติดตั้ง.)
เบนเจมส์

2
บริษัท ของเราจบลงด้วยการเลือกคอมไพล์เพราะการสนับสนุนที่ดีบน Windows - เช็คเอาท์Git ส่วนขยาย ฉันลำเอียงเพราะตอนนี้ฉันเป็นผู้มีส่วนร่วม แต่ฉันไม่ใช่เมื่อเราเริ่มใช้มัน
จาค็อบสแตนลีย์

11

หลังจากอ่านไปหมดแล้ว Mercurial นั้นง่ายกว่า (ซึ่งฉันก็ยังเชื่อว่ามันคือหลังจากชุมชนอินเทอร์เน็ตทั้งหมดมีความเห็น) เมื่อฉันเริ่มทำงานกับ Git และ Mercurial ฉันรู้สึกว่า Git นั้นค่อนข้างง่ายสำหรับฉันที่จะปรับตัวให้เข้ากับ กับ Mercurial with TortoiseHg) เมื่อทำงานจากบรรทัดคำสั่งส่วนใหญ่เป็นเพราะคำสั่ง git ถูกตั้งชื่ออย่างเหมาะสมตามฉันและมีจำนวนน้อยกว่า Mercurial มีการตั้งชื่อที่แตกต่างกันสำหรับแต่ละคำสั่งที่ทำงานแตกต่างกันในขณะที่คำสั่ง Git สามารถใช้งานได้หลากหลายตามสถานการณ์ (เช่นcheckout) ในขณะที่ Git ยากขึ้นในตอนนี้ความแตกต่างก็มีอยู่มากมาย YMMV .. ด้วยไคลเอนต์ GUI ที่ดีเช่น TortoiseHg จริง ๆ แล้วมันง่ายกว่ามากที่จะทำงานกับ Mercurial และฉันไม่จำเป็นต้องจำคำสั่งที่สับสนเล็กน้อย ฉันจะไม่ลงรายละเอียดว่าคำสั่งสำหรับการดำเนินการเหมือนกันทุกที่แตกต่างกัน แต่ที่นี่มีสองรายการที่ครอบคลุม: 1 จากเว็บไซต์ของตัวเองของ Mercurialและที่ 2 จาก wikivs

╔═════════════════════════════╦════════════════════════════════════════════════════════════════════════════════════════════════╗
║           Git               ║                Mercurial                                                                       ║
╠═════════════════════════════╬════════════════════════════════════════════════════════════════════════════════════════════════╣
║ git pull                    ║ hg pull -u                                                                                     ║
║ git fetch                   ║ hg pull                                                                                        ║
║ git reset --hard            ║ hg up -C                                                                                       ║
║ git revert <commit>         ║ hg backout <cset>                                                                              ║
║ git add <new_file>          ║ hg add <new_file> (Only equivalent when <new_file> is not tracked.)                            ║
║ git add <file>              ║ Not necessary in Mercurial.                                                                    ║
║ git add -i                  ║ hg record                                                                                      ║
║ git commit -a               ║ hg commit                                                                                      ║
║ git commit --amend          ║ hg commit --amend                                                                              ║
║ git blame                   ║ hg blame or hg annotate                                                                        ║
║ git blame -C                ║ (closest equivalent): hg grep --all                                                            ║
║ git bisect                  ║ hg bisect                                                                                      ║
║ git rebase --interactive    ║ hg histedit <base cset> (Requires the HisteditExtension.)                                      ║
║ git stash                   ║ hg shelve (Requires the ShelveExtension or the AtticExtension.)                                ║
║ git merge                   ║ hg merge                                                                                       ║
║ git cherry-pick <commit>    ║ hg graft <cset>                                                                                ║
║ git rebase <upstream>       ║ hg rebase -d <cset> (Requires the RebaseExtension.)                                            ║
║ git format-patch <commits>  ║ hg email -r <csets> (Requires the PatchbombExtension.)                                         ║
║   and git send-mail         ║                                                                                                ║
║ git am <mbox>               ║ hg mimport -m <mbox> (Requires the MboxExtension and the MqExtension. Imports patches to mq.)  ║
║ git checkout HEAD           ║ hg update                                                                                      ║
║ git log -n                  ║ hg log --limit n                                                                               ║
║ git push                    ║ hg push                                                                                        ║
╚═════════════════════════════╩════════════════════════════════════════════════════════════════════════════════════════════════╝

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

สิ่งที่ฉันพลาดใน Hg คือคุณสมบัติ submodule ของ Git Hg มีเนื้อหาย่อย แต่นั่นไม่ใช่ God submodule

ระบบนิเวศรอบ ๆ ทั้งสองยังสามารถมีอิทธิพลต่อการเลือกของตัวเอง: Git ต้องเป็นที่นิยมมากขึ้น (แต่ไม่สำคัญ) Git มีGitHubในขณะที่ Mercurial มีBitBucket Mercurial มี TortoiseHg ซึ่งฉันไม่เคยเห็นอะไรที่ดีเทียบเท่า Git

แต่ละคนมีข้อดีและข้อเสียด้วยทั้งสองอย่างคุณจะไม่แพ้


8

ลองดูโพสต์ของ Scott Chaconสักพัก

ฉันคิดว่าคอมไพล์มีชื่อเสียงว่าเป็น "ซับซ้อนกว่า" แม้ว่าในประสบการณ์ของฉันมันไม่ซับซ้อนเกินกว่าที่มันจะต้องเป็น IMO, รุ่นคอมไพล์เป็นวิธีที่ง่ายต่อการเข้าใจ (แท็กประกอบด้วยกระทำ (และตัวชี้ไปยังศูนย์หรือมากกว่ากระทำของผู้ปกครอง) ประกอบด้วยต้นไม้ประกอบด้วย blobs และต้นไม้อื่น ๆ ... ทำ)

มันไม่ใช่แค่ประสบการณ์ของฉันที่คอมไพล์ไม่สับสนมากกว่า Mercurial ฉันขอแนะนำให้อ่านโพสต์บล็อกนี้จาก Scott Chaconอีกครั้งในเรื่องนี้


1
แบบจำลอง Mercurial แทบจะเหมือนกันเกือบทั้งหมด: เปลี่ยนจุดชี้ไปที่จุดชัดแจ้งเพื่อแก้ไขไฟล์ / หยด ... เสร็จแล้ว หากคุณกำลังเปรียบเทียบรูปแบบบนดิสก์คุณอาจไม่ได้อธิบายถึงไฟล์แพ็คซึ่งมีความยุ่งยากในการอธิบายมากกว่ารูปแบบ revlog อย่างง่ายจาก hg
tonfa

แบบง่ายนั้นละเว้นการติดแท็กซึ่งเป็น clunkier มากในทางปฏิบัติใน hg (แม้ว่าฉันจะยืนยันว่าแท็ก git นั้นสับสนเล็กน้อยเพราะมันไม่ได้สร้างวัตถุแท็กตามค่าเริ่มต้น) รูปแบบบนดิสก์มีราคาแพงเป็นพิเศษสำหรับทั้งสองโครงการที่มีประวัติชื่อไฟล์จำนวนมาก
ดัสติน

1
ฉันไม่คิดว่าแบบจำลองนี้จะละเว้นการติดแท็ก: การติดแท็กเป็นเรื่องเล็กน้อยใน Mercurial - อย่างที่คุณรู้มันเป็นแค่ไฟล์ที่ให้ชื่อกับแฮช SHA-1 ไม่มีการคาดเดาว่าแท็กจะไหลไปมาในระบบอย่างไร: พวกมันเคลื่อนที่ไปพร้อมกับการผลักและดึง และหากมีข้อขัดแย้งของแท็กก็เป็นเรื่องง่ายที่จะแก้ปัญหา: คุณแก้ไขได้เหมือนความขัดแย้งอื่น ๆ ท้ายที่สุดมันเป็นเพียงบรรทัดในไฟล์ข้อความ ฉันคิดว่าความเรียบง่ายของรุ่นนี้เป็นคุณสมบัติที่ดีมาก
Martin Geisler

ดัสติน: ใช่ผู้ใช้มักจะสับสนกับความจริงที่ว่าคุณไม่เห็นแท็ก 1.0 ใน.hgtagsเมื่อคุณตรวจสอบการแก้ไข 1.0 อย่างไรก็ตามคุณไม่จำเป็นต้องมองเข้าไปข้างใน.hgtagsและคุณจะพบว่าhg tagsยังคงมีรายการแท็กทั้งหมด นอกจากนี้พฤติกรรมนี้เป็นผลจากการจัดเก็บแท็กในไฟล์ที่ควบคุมเวอร์ชันแบบง่าย ๆ อีกครั้งแบบจำลองนั้นง่ายต่อการเข้าใจและคาดเดาได้มาก
Martin Geisler

1
Martin Geislerฉันขอยืนยันว่ากฎสำหรับแท็กใน Mercurial จำเป็นต้องใช้เพราะมันใช้ไฟล์ที่ควบคุมเวอร์ชันสำหรับการขนส่งพร้อมเลเยอร์ในกฎพิเศษเพื่อทำให้แท็กที่ไม่มีเวอร์ชันเป็นอะไรที่ง่ายต่อการเข้าใจ
Jakub Narębski

5

ฉันใช้ Git มานานกว่าหนึ่งปีในงานปัจจุบันของฉันและก่อนหน้านั้นเคยใช้ Mercurial มานานกว่าหนึ่งปีในงานก่อนหน้านี้ของฉัน ฉันจะให้การประเมินจากมุมมองของผู้ใช้

ก่อนอื่นทั้งคู่เป็นระบบควบคุมเวอร์ชันแบบกระจาย ระบบควบคุมเวอร์ชันแบบกระจายต้องเปลี่ยนความคิดจากระบบควบคุมเวอร์ชันดั้งเดิม แต่จริง ๆ แล้วจะทำงานได้ดีขึ้นในหลาย ๆ ทางเมื่อมีคนเข้าใจพวกเขา ด้วยเหตุนี้ฉันจึงพิจารณาทั้ง Git และ Mercurial ที่เหนือกว่า Subversion, Perforce และอื่น ๆ ความแตกต่างระหว่างระบบควบคุมเวอร์ชันแบบกระจายและระบบควบคุมเวอร์ชันดั้งเดิมนั้นใหญ่กว่าความแตกต่างระหว่าง Git และ Mercurial

อย่างไรก็ตามยังมีความแตกต่างที่สำคัญระหว่าง Git และ Mercurial ซึ่งทำให้แต่ละแบบนั้นเหมาะกับกรณีการใช้งานของตัวเอง

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

ส่วนหนึ่งเป็นเพราะ Mercurial เป็นเพียงตัวทำความสะอาดธรรมดา คุณไม่ค่อยต้องแยกสาขาด้วยตนเองใน Mercurial Mercurial จะสร้างสาขาที่ไม่ระบุตัวตนให้คุณโดยอัตโนมัติหากคุณต้องการ ระบบการตั้งชื่อ Mercurial นั้นง่ายกว่า คุณไม่ต้องกังวลกับความแตกต่างระหว่าง "ดึงข้อมูล" และ "ดึง" เหมือนกับที่คุณทำกับ Git Mercurial เป็นรถบั๊กน้อยลงเล็กน้อย มีปัญหาเรื่องความไวของชื่อไฟล์ที่ใช้เพื่อทำให้เกิดปัญหาเมื่อกดโครงการข้ามแพลตฟอร์มที่มีทั้ง Git และ Mercurial สิ่งนี้ได้รับการแก้ไขใน Mercurial เมื่อไม่นานมานี้ในขณะที่พวกเขาไม่ได้รับการแก้ไขใน Git ครั้งล่าสุดที่ฉันตรวจสอบ คุณสามารถบอก Mercurial เกี่ยวกับการเปลี่ยนชื่อไฟล์ ด้วย Git หากไม่พบการเปลี่ยนชื่อโดยอัตโนมัติ - เป็นข้อเสนอที่ได้รับความนิยมหรือพลาดในการใช้งานของฉัน - การเปลี่ยนชื่อไม่สามารถติดตามได้เลย

เหตุผลอื่นสำหรับความซับซ้อนเพิ่มเติมของ Git คือมีความจำเป็นอย่างยิ่งที่จะต้องสนับสนุนคุณสมบัติและกำลังไฟเพิ่มเติม ใช่มันซับซ้อนกว่าในการจัดการกิ่งใน Git - แต่ในทางกลับกันเมื่อคุณมีกิ่งแล้วก็ไม่ยากเกินไปที่จะทำสิ่งต่าง ๆ กับกิ่งเหล่านั้นที่แทบจะเป็นไปไม่ได้ใน Mercurial กิ่งที่หักออกเป็นหนึ่งในสิ่งเหล่านี้: คุณสามารถย้ายสาขาของคุณเพื่อให้ฐานของมันแทนที่จะเป็นสถานะของลำต้นเมื่อคุณแยกแขนงเป็นสถานะของลำต้นตอนนี้; สิ่งนี้จะลดความซับซ้อนของประวัติรุ่นเมื่อมีคนจำนวนมากทำงานบนฐานรหัสเดียวกันเนื่องจากการกดแต่ละครั้งที่ลำตัวสามารถทำให้ปรากฏขึ้นตามลำดับแทนที่จะเป็นพัน ในทำนองเดียวกันการยุบหลายคอมมิตในสาขาของคุณเป็นการกระทำเดียวง่ายกว่ามาก

ในที่สุดฉันคิดว่าทางเลือกระหว่าง Mercurial และ Git ควรขึ้นอยู่กับว่าโครงการควบคุมเวอร์ชันของคุณมีขนาดใหญ่เพียงใดโดยวัดจากจำนวนคนที่ทำงานกับพวกเขาพร้อมกัน หากคุณมีกลุ่มของโหลหรือมากกว่านั้นทำงานบนเว็บแอพพลิเคชั่นเสาหินเดียวตัวอย่างเช่นเครื่องมือการจัดการสาขาที่มีประสิทธิภาพยิ่งขึ้นของ Git จะทำให้มันเหมาะสำหรับโครงการของคุณมากขึ้น ในทางกลับกันหากทีมของคุณกำลังพัฒนาระบบการกระจายที่ต่างกันโดยมีนักพัฒนาเพียงหนึ่งหรือสองคนที่ทำงานกับส่วนประกอบใด ๆ ในเวลาเดียวกันโดยใช้ที่เก็บ Mercurial สำหรับแต่ละโครงการจะช่วยให้การพัฒนาดำเนินไปอย่างราบรื่นมากขึ้น ค่าใช้จ่ายในการจัดการพื้นที่เก็บข้อมูล

Bottom line: หากคุณมีทีมใหญ่พัฒนาแอพพลิเคชั่นขนาดใหญ่ใช้ Git; หากแอปพลิเคชั่นส่วนบุคคลของคุณมีขนาดเล็กโดยที่ขนาดใดก็ตามที่มาจากตัวเลขแทนที่จะเป็นขนาดของแอพพลิเคชั่นดังกล่าวให้ใช้ Mercurial


4

ข้อแตกต่างประการหนึ่งที่ไม่เกี่ยวข้องกับ DVCS ทั้งหมด:

Git ดูเหมือนจะได้รับความนิยมจากนักพัฒนา C Git เป็นแหล่งเก็บข้อมูลสำหรับลินุกซ์เคอร์เนลและนี่อาจเป็นเหตุผลว่าทำไมมันจึงเป็นที่นิยมของนักพัฒนา C นี่เป็นเรื่องจริงโดยเฉพาะอย่างยิ่งสำหรับผู้ที่มีความหรูหราในการทำงานในโลก Linux / Unix เท่านั้น

ผู้พัฒนา Java ดูเหมือนจะชอบ Mercurial มากกว่า Git อาจมีเหตุผลสองประการคือหนึ่งในนั้นมีโปรเจ็กต์ Java ขนาดใหญ่จำนวนมากที่โฮสต์บน Mercurial รวมถึง JDK เอง อีกอย่างหนึ่งก็คือโครงสร้างและเอกสารประกอบที่ชัดเจนของ Mercurial appeals สำหรับผู้ที่มาจากค่าย Java ในขณะที่คนเหล่านั้นพบว่าการตั้งชื่อคำสั่ง wrt ของ Git ไม่สอดคล้องกันและไม่มีเอกสารประกอบ ฉันไม่ได้บอกว่าเป็นเรื่องจริงฉันกำลังบอกว่าผู้คนคุ้นเคยกับบางสิ่งบางอย่างจากที่อยู่อาศัยปกติของพวกเขาแล้วพวกเขาก็มักจะเลือก DVCS จากสิ่งนั้น

นักพัฒนางูใหญ่เกือบจะชอบ Mercurial โดยเฉพาะฉันจะถือว่า ไม่มีเหตุผลที่เป็นจริงสำหรับสิ่งนั้นนอกจากความจริงที่ว่า Mercurial ใช้ Python (ฉันใช้ Mercurial ด้วยและฉันก็ไม่เข้าใจจริงๆว่าทำไมผู้คนถึงเอะอะเกี่ยวกับการใช้ภาษาของ DVCS ฉันไม่เข้าใจคำของ Python และถ้ามันไม่ได้อยู่ในรายการที่มันอยู่ที่ไหน เป็นไปตาม Python แล้วฉันจะไม่ทราบ)

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

(ไม่ฉันไม่มีสถิติการใช้งานเพื่อสำรองการอ้างสิทธิ์ของฉันด้านบน .. มันทั้งหมดขึ้นอยู่กับความคิดของฉัน)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.