เหตุใด git pull จึงทำการผสานแทนที่จะเป็น rebase โดยปริยาย


71

พิจารณาสถานการณ์ต่อไปนี้:

  • คุณมีที่เก็บโคลนคอมไพล์
  • คุณมีการกระทำในท้องถิ่น (การกระทำที่ยังไม่ได้ผลักไปที่ใดก็ได้)
  • ที่เก็บรีโมตมีการยอมรับใหม่ที่คุณยังไม่ได้กระทบยอด

ดังนั้นสิ่งนี้:

ไม่รวมการกระทำ

หากคุณดำเนินการgit pullด้วยการตั้งค่าเริ่มต้นคุณจะได้รับสิ่งนี้:

ผสานกระทำ

นี่เป็นเพราะคอมไพล์ทำการผสาน

มีทางเลือกแม้ว่า คุณสามารถบอกให้ pull ทำ rebase แทน:

git pull --rebase

และคุณจะได้รับสิ่งนี้:

rebased

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

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

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

มันได้รับการแนะนำว่าคำถามนี้เป็นคำถามที่ซ้ำกันของเหตุใดเว็บไซต์จำนวนมากจึงนิยมใช้“ git rebase” มากกว่า“ git merge” ; อย่างไรก็ตามคำถามนี้ค่อนข้างตรงกันข้ามกับคำถามนี้ มันกล่าวถึงข้อดีของการ rebase มากกว่าการรวมในขณะที่คำถามนี้ถามเกี่ยวกับประโยชน์ของการรวมมากกว่า rebase คำตอบที่สะท้อนให้เห็นถึงเรื่องนี้โดยมุ่งเน้นไปที่ปัญหาเกี่ยวกับการรวมและผลประโยชน์ของการคืนเงิน



อีกปัญหาคือถ้าคุณตั้งใจที่จะเป็นปรมาจารย์แล้วทำการดึงที่รวมกันแล้วทั้งสองคนจะไม่ซิงค์แม้ว่าการผสานจะดูปกติ นี่คือเหตุผลที่นามแฝงดึงของฉันมีเฉพาะ --ff เท่านั้น
Ixrec

ถ้า sourcetree เปลี่ยนมุมมองกราฟของมันเพื่อให้แสดง rebases / การผสานต่างกันคุณจะเปลี่ยนเป็นการรวมกันหรือไม่
Ewan

1
@Ewan SourceTree ไม่ควรเปลี่ยนมุมมองกราฟของสิ่งนี้ มันแสดงกราฟได้อย่างถูกต้อง
jpmc26

4
สำหรับผู้มีสิทธิ์ลงคะแนนเสียงซ้ำโปรดทราบว่าเนื้อหาในคำตอบที่ฉันยอมรับนั้นส่วนใหญ่ไม่ปรากฏในคำถามที่คุณอ้างว่าซ้ำซ้อน
jpmc26

คำตอบ:


56

เป็นการยากที่จะทราบได้อย่างแน่นอนว่าเหตุใดการผสานจึงเป็นค่าเริ่มต้นโดยไม่ได้ยินจากผู้ที่ทำการตัดสินใจ

นี่คือทฤษฎี ...

Git ไม่สามารถสันนิษฐานได้ว่ามันเป็นเรื่องง่ายที่จะ - ประเมินทุก ๆ ครั้ง ฟังวิธีการที่เสียง "Rebase ทุก ๆ การดึง" ฟังดูผิดถ้าคุณใช้คำขอดึงหรือคล้ายกัน คุณจะลดการขอดึงได้หรือไม่?

ในทีมที่ไม่เพียง แต่ใช้ Git สำหรับการควบคุมแหล่งที่มาจากส่วนกลาง ...

  • คุณสามารถดึงจากต้นน้ำและจากปลายน้ำ บางคนดึงมาจากปลายน้ำมากจากผู้มีส่วนร่วมเป็นต้น

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

Git ได้รับการออกแบบมาสำหรับทีมที่มีการกระจายตัวสูงซึ่งทุกคนไม่ได้ดึงและผลักดันไปสู่ ​​repo ส่วนกลางเดียว ดังนั้นค่าเริ่มต้นทำให้รู้สึก

  • นักพัฒนาที่ไม่ทราบว่าเมื่อใดที่การรีบูตจะเป็นการรวมตัวตามค่าเริ่มต้น
  • นักพัฒนาสามารถรีบูตเมื่อพวกเขาต้องการ
  • ผู้ใช้ที่ดึงจำนวนมากและดึงจำนวนมากจะได้รับค่าเริ่มต้นที่เหมาะสมกับพวกเขาที่สุด

สำหรับหลักฐานของเจตนานี่คือลิงค์ไปยังอีเมลที่รู้จักกันดีจาก Linus Torvalds โดยมีความเห็นของเขาว่าเมื่อใดที่พวกเขาไม่ควรรีบูท อีเมลดึงข้อมูล Dri-Devel

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

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

คำแนะนำ:อย่าสร้างนโยบายในการเปลี่ยนค่าเริ่มต้น ทุกครั้งที่คุณรวม Git เข้ากับกลุ่มนักพัฒนาขนาดใหญ่นักพัฒนาบางคนจะไม่เข้าใจ Git ทั้งหมด (รวมถึงตัวเอง) พวกเขาจะไปที่ Google ดังนั้นรับคำแนะนำตำราเรียนแล้วสงสัยว่าทำไมบางอย่างไม่ทำงานเช่นทำไมgit checkout --ours <path>ไฟล์ผิดรุ่น? คุณสามารถแก้ไขสภาพแวดล้อมในท้องถิ่นของคุณสร้างนามแฝง ฯลฯ เพื่อให้เหมาะกับรสนิยมของคุณ


5
+1 สำหรับการไม่เปลี่ยนค่าเริ่มต้น - แทนที่จะหมุนเวิร์กโฟลว์คอมไพล์ของคุณเองมันอาจจะดีกว่าที่จะคว้าสิ่งที่มีอยู่ (เช่นสิ่งใด ๆ ที่จัดทำโดย Atlassian atlassian.com/git/tutorials/comparing-workflows/ ...... )
Rob Church

1
ขอบคุณสำหรับคำตอบ. ข้อมูลเกี่ยวกับการดึงจากปลายน้ำคือสิ่งที่ฉันพลาด อีกอย่างที่น่าสนใจมากคือลิงก์ที่คุณให้กำลังใจสิ่งที่ฉันต้องการให้บรรลุ: "ผู้คนสามารถ (และอาจจะควร) ลดต้นไม้ส่วนตัวของพวกเขา (งานของตัวเอง)"
jpmc26

2
@jpmc ยอดเยี่ยม จริง การรีบูทต้นไม้ส่วนตัวสามารถขัดขวางความยุ่งเหยิงมากมายจากประวัติศาสตร์ที่แบ่งปัน ฉันทำมัน. มันเป็นความชัดเจนในเมื่อไม่ทำมันเป็นสิ่งสำคัญ
joshp

"นักพัฒนาบางคนไม่เข้าใจ Git ทั้งหมด" Rebase ไม่ใช่คุณสมบัติแฟนซี ("deep" และอื่น ๆ ) ของ Git คุณพิจารณาสิ่งนี้ยากที่จะเข้าใจหรือไม่? ฉันคิดว่านี่น่าจะเป็นตัวกระตุ้นให้โทรหาคนไร้ความสามารถ
Victor Yarema

15

หากคุณอ่าน manpage git เพื่อทำการ rebase มันจะบอกว่า :

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

ฉันคิดว่ามันบอกว่ามันดีพอที่จะไม่ใช้ rebase เลยให้ทำอย่างเดียวโดยอัตโนมัติทุกครั้ง บางคนพิจารณาrebase จะเป็นอันตราย บางทีมันอาจจะไม่เคยถูกใส่เข้าไปในคอมไพล์เลยเพราะสิ่งที่ดูเหมือนจะทำคือทำให้ประวัติศาสตร์น่าสนใจสิ่งที่ไม่ควรมีความจำเป็นใน SCM ใด ๆ ที่มีหน้าที่สำคัญเพียงอย่างเดียวคือการรักษาประวัติ

เมื่อคุณพูดว่า 'รักษา ... ประวัติที่สะอาด' ให้คิดว่าคุณผิด มันอาจดูดีกว่า แต่สำหรับเครื่องมือที่ออกแบบมาเพื่อเก็บประวัติของการแก้ไขมันจะสะอาดกว่าการกระทำทุกอย่างเพื่อให้คุณสามารถเห็นสิ่งที่เกิดขึ้น ฆ่าเชื้อประวัติศาสตร์หลังจากนั้นก็เหมือนขัดคราบออกไปทำให้ดูโบราณที่อุดมไปด้วยเช่น repro- เงา :-)


3
@Ewan IMHO "ไม่ได้ผล แต่หน้าตาดี" เป็นสิ่งที่ควรสงวนไว้สำหรับอุตสาหกรรมแฟชั่นเท่านั้นไม่ใช่ไอที IMHO git ควรลบออกเพราะเห็นได้ชัดว่ามันกระตุ้นให้คนจำนวนมากเกินไปที่จะคิดว่ารูปแบบสำคัญกว่าเนื้อหา
gbjbaanb

12
ฉันจะโต้แย้งข้อเสนอแนะของคุณว่าการรักษาความสะอาดของประวัติศาสตร์นั้นไร้ประโยชน์ มันไม่ใช่. ประวัติพื้นที่เก็บข้อมูลมีไว้สำหรับการบริโภคของมนุษย์และดังนั้นจึงมีค่ามากในการทำให้สามารถอ่านได้ ในกรณีการใช้งานของฉันโดยเฉพาะเรายังตั้งใจว่าผู้จัดการโครงการที่ไม่ใช่นักพัฒนาควรสามารถอ่านประวัติได้ ประวัติการทำความสะอาดสามารถช่วยได้เท่านั้นและสามารถช่วยนักพัฒนาใหม่ที่ไม่เคยเห็นรหัสฐานและต้องดำน้ำในและแก้ไขข้อผิดพลาดเข้าใจสิ่งที่เกิดขึ้นในส่วนของรหัสเฉพาะ
jpmc26

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

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

4
คุณไม่ต้องการ "เก็บประวัติการแก้ไข" ไว้อย่างแน่นอนหากนั่นรวมถึงการกระทำที่นักพัฒนาได้ทำไว้ ตามตรรกะนั้นเราควรบันทึกรหัสดั้งเดิมทุกครั้งที่กดปุ่ม backspace การมอบอำนาจทุกครั้งควรเป็นการเปลี่ยนแปลงเล็กน้อยและสมบูรณ์ซึ่งยังคงทำให้โครงการทั้งหมดอยู่ในสภาพมั่นคง หากพบว่าการคอมมิชชันดั้งเดิมของคุณในภายหลังเป็นบั๊กกการดีดตัว / แก้ไข / แก้ไขการคอมมิตมากกว่าการสร้างคอมมิท อย่างไรก็ตามโปรดดูที่mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html
Mikko Rantalainen

12

คุณถูกต้องสมมติว่าคุณมีที่เก็บข้อมูลในพื้นที่ / เปลี่ยนแปลงเพียงแห่งเดียว อย่างไรก็ตามให้พิจารณาว่ามีพีซีในพื้นที่เครื่องที่สองเช่น

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

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


ความแตกต่างที่สอง: กลยุทธ์การผสานจะทำให้โครงสร้างที่สอดคล้องและชัดเจนในเวลา หลังจาก rebases เป็นไปได้มากที่การกระทำที่เก่ากว่าอาจตามการเปลี่ยนแปลงใหม่ทำให้ประวัติศาสตร์ทั้งหมดและการไหลของมันยากที่จะเข้าใจ


1
"หลังจากการรีบูตเป็นไปได้มากที่การกระทำที่เก่ากว่าอาจตามการเปลี่ยนแปลงที่ใหม่กว่า" - ซึ่งเกิดขึ้นจากการรวมเช่นกันซึ่งเป็นสาเหตุที่คุณ (อาจ) ต้องการกราฟสวย ๆ เพื่อให้เข้าใจได้ เวลาที่กระทำได้อาจนานก่อนที่การผสานที่นำมาไว้ในสาขานี้
Steve Jessop

6

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

ฉันใช้git pull --rebaseค่อนข้างมากใน repo ส่วนตัวของฉัน แต่ถึงแม้จะมีข้อเสียที่อาจเกิดขึ้นซึ่งเป็นประวัติของฉันHEADไม่สะท้อนต้นไม้ในขณะที่ฉันทำงานกับมัน

ดังนั้นสำหรับตัวอย่างใหญ่สมมติว่าฉันมักจะทำการทดสอบและตรวจสอบให้แน่ใจว่าพวกเขาผ่านก่อนที่จะทำการกระทำ สิ่งนี้มีความเกี่ยวข้องน้อยกว่าหลังจากที่ฉันทำgit pull --rebaseเพราะมันไม่เป็นความจริงอีกต่อไปว่าต้นไม้ในแต่ละการกระทำของฉันได้ผ่านการทดสอบแล้ว ตราบใดที่การเปลี่ยนแปลงไม่ได้รบกวน แต่อย่างใดและรหัสที่ฉันดึงได้รับการทดสอบแล้วก็น่าจะผ่านการทดสอบ แต่เราไม่รู้เพราะฉันไม่เคยลอง หากการบูรณาการอย่างต่อเนื่องเป็นส่วนสำคัญของเวิร์กโฟลว์ของคุณการรีบูตใด ๆ ใน repo ที่ CIed กำลังเป็นปัญหา

ฉันไม่ได้สนใจเรื่องนี้ แต่มันรบกวนบางคน: พวกเขาต้องการให้ประวัติของพวกเขาในคอมไพล์สะท้อนให้เห็นถึงรหัสที่พวกเขาใช้งานได้จริง (หรืออาจตามเวลาที่พวกเขาผลักดันมันเป็นเวอร์ชั่นที่เรียบง่ายของความจริงหลังจากการใช้ จาก "fixup")

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

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