ความแตกต่างระหว่าง 'git merge' และ 'git rebase' คืออะไร?


499

ความแตกต่างระหว่างgit mergeและgit rebaseคืออะไร


14
ตั้งแต่คำตอบของฉันถูกลบไปที่ลิงค์นี้เพื่อรับคำตอบที่ถูกต้องสำหรับคำถามนี้: git-scm.com/book/en/Git-Branching-Rebasing#The-Basic-Rebase
HiB

6
โดยวิธีการที่ฉันจะเพิ่มเว็บไซต์นี้ สิ่งที่คุณต้องรู้เกี่ยวกับคอมไพล์เรียนรู้โดยการเล่น: pcottle.github.io/learnGitBranching
Rollyng

อ่านก่อนนี้: git-scm.com/book/en/v2/…จากนั้น: git-scm.com/book/en/v2/Git-Branching-Rebasingคุณจะเข้าใจจริงๆ
Liber

คำตอบ:


867

สมมติว่าเดิมมี 3 กระทำ, A, B, C:

เอบีซี

จากนั้นนักพัฒนาสร้างแดนกระทำDและนักพัฒนาสร้างเอ็ดกระทำE:

ABCDE

เห็นได้ชัดว่าความขัดแย้งนี้ควรได้รับการแก้ไขอย่างใด สำหรับสิ่งนี้มี 2 วิธี:

รวม :

ABCDEM

ทั้งสองกระทำDและEยังคงอยู่ที่นี่ แต่เราจะสร้างการผสานกระทำMที่สืบทอดการเปลี่ยนแปลงทั้งจากและD Eอย่างไรก็ตามสิ่งนี้สร้างรูปร่างของเพชรซึ่งหลายคนพบว่าสับสนมาก

การอ้างอิง :

ABCDER

เราสร้างคอมRมิชชันซึ่งเนื้อหาไฟล์จริงนั้นเหมือนกับคอมมิชชันคอมมิชชันMด้านบน แต่เรากำจัดการกระทำEเหมือนที่มันไม่เคยมีอยู่ (แสดงโดยจุด - เส้นที่หายไป) เนื่องจากข้อ จำกัด นี้Eควรอยู่ในพื้นที่ของนักพัฒนา Ed และไม่เคยถูกผลักไปยังที่เก็บอื่น ข้อได้เปรียบของการรีบูตคือการหลีกเลี่ยงรูปทรงเพชรและประวัติศาสตร์ยังคงเป็นเส้นตรงที่ดีนักพัฒนาส่วนใหญ่ชอบที่!


53
ภาพประกอบที่ดี อย่างไรก็ตามฉันไม่เห็นด้วยอย่างเต็มที่กับน้ำเสียงบวกที่มีการจัดการการคืนเงิน ในทั้งการรวมและการขัดแย้งการรีบูตสามารถเกิดขึ้นได้ที่ต้องการการแก้ไขด้วยตนเอง และเช่นเคยเมื่อโปรแกรมเมอร์มีส่วนร่วมมีโอกาสที่ไม่อาจละเลยข้อผิดพลาดหรือที่รู้จักกันในข้อผิดพลาด หากมีข้อผิดพลาดในการรวมเกิดขึ้นทั้งทีมหรือชุมชนสามารถเห็นการรวมและตรวจสอบว่ามีการแนะนำบั๊กหรือไม่ ประวัติของการรีบูตยังคงอยู่ใน repo ของนักพัฒนา 1 คนและถึงแม้จะมีเพียงอายุการใช้งานที่ จำกัด ในการอ้างอิง มันอาจดูดีกว่า แต่ไม่มีใครสามารถมองเห็นสิ่งที่ผิดพลาดได้อย่างง่ายดาย
Uwe Geuder

> "อย่างไรก็ตามสิ่งนี้สร้างรูปร่างของเพชรซึ่งหลายคนพบว่าสับสนมาก" อืม ... คุณอธิบายได้ไหม?
Greg Maletic

@GregMaletic: รูปร่างเพชรเป็นประวัติที่ไม่ใช่เชิงเส้น ฉันไม่รู้เกี่ยวกับคุณ แต่ฉันไม่ชอบสิ่งที่ไม่ใช่เชิงเส้นโดยทั่วไป ที่กล่าวว่าคุณสามารถใช้ผสานกับเพชรได้หากคุณต้องการจริงๆ - ไม่มีใครบังคับให้คุณ
mvp

1
แม้ว่าคำตอบนี้จะเป็นประโยชน์อย่างยิ่ง แต่ก็จะดีกว่าถ้าคุณเพิ่มคำสั่ง git จริงด้วยไฟล์ foo.txt อย่างง่าย ๆ เพื่อสร้างมันซ้ำในเครื่อง เช่นเดียวกับผู้ใช้ล่าสุดกล่าวว่าไม่ชัดเจนว่าใครกำลังทำ rebase
Vortex

1
@ pferrel: l อย่าคิดว่าคุณได้รับมันอย่างถูกต้อง git mergeไม่แทรกสอด (แต่มันอาจปรากฏขึ้นโดยดูที่git log) แต่git mergeให้รักษาทั้งประวัติศาสตร์การพัฒนาโดยแดนและเอ็ดไว้เหมือนเดิมตามที่เห็นจากแต่ละมุมมองในแต่ละครั้ง git rebaseทำให้ดูเหมือนว่า Dan ทำงานกับมันก่อนและเอ็ดก็ติดตามเขา ในทั้งสองกรณี (ผสานและรีบูต) ทรีไฟล์ผลลัพธ์ที่แท้จริงนั้นเหมือนกันทุกประการ
MVP

158

ฉันรักข้อความที่ตัดตอนมานี้จาก10 สิ่งที่ฉันเกลียดเกี่ยวกับคอมไพล์ (มันให้คำอธิบายสั้น ๆ สำหรับการรีบูตในตัวอย่างที่สอง):

3. เอกสารเส็งเคร็ง

หน้า man เป็นหนึ่งยิ่ง“ f *** you” 1 . พวกเขาอธิบายคำสั่งจากมุมมองของนักวิทยาศาสตร์คอมพิวเตอร์ไม่ใช่ผู้ใช้ กรณีในจุด:

git-push – Update remote refs along with associated objects

นี่คือคำอธิบายสำหรับมนุษย์:

git-push – Upload changes from your local repository into a remote repository

อัปเดตอีกตัวอย่าง: (ขอบคุณ cgd)

git-rebase – Forward-port local commits to the updated upstream head

แปล:

git-rebase – Sequentially regenerate a series of commits so they can be 
             applied directly to the head node

แล้วเราก็มี

git-merge - Join two or more development histories together

ซึ่งเป็นคำอธิบายที่ดี


1. ไม่แน่ใจในต้นฉบับ


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

128

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

หากต้องการอธิบายด้วยคำพูด:

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

ด้วยเหตุผลที่ฉันไม่เข้าใจเครื่องมือ GUI สำหรับ Git ไม่เคยใช้ความพยายามอย่างมากในการนำเสนอประวัติการผสานอย่างชัดเจนยิ่งขึ้น ดังนั้นหากคุณต้องการ "ประวัติการทำความสะอาด" คุณต้องใช้การลดระดับ

ฉันดูเหมือนจะจำได้ว่าได้อ่านโพสต์บล็อกจากโปรแกรมเมอร์ที่ใช้ rebase เท่านั้นและอื่น ๆ ที่ไม่เคยใช้ rebase

ตัวอย่าง

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

Write tutorial
Merge remote-tracking branch 'origin/master' into fixdocs
Bigger buttons
Drop down list
Extend README
Merge remote-tracking branch 'origin/master' into fixdocs
Make window larger
Fix a mistake in howto.md

กล่าวคือการรวมและ UI กระทำระหว่างการทำเอกสารของคุณ

หากคุณรีบูตโค้ดของคุณไปที่มาสเตอร์แทนที่จะผสานมันจะมีลักษณะเช่นนี้:

Write tutorial
Extend README
Fix a mistake in howto.md
Bigger buttons
Drop down list
Make window larger

ความมุ่งมั่นทั้งหมดของคุณอยู่ที่ด้านบน (ใหม่ที่สุด) ตามด้วยส่วนที่เหลือของmasterสาขา

( ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้เขียนโพสต์ "10 สิ่งที่ฉันเกลียดเกี่ยวกับ Git" ที่อ้างถึงในคำตอบอื่น )


42

แม้ว่าคำตอบที่ได้รับการยอมรับและได้รับการโหวตมากที่สุดนั้นยอดเยี่ยม แต่ฉันก็พบว่ามันมีประโยชน์ในการอธิบายความแตกต่างด้วยคำพูดเท่านั้น:

ผสาน

  • “ โอเคเรามีสถานะการเก็บข้อมูลที่แตกต่างกันสองสถานะ ลองผสานเข้าด้วยกัน ผู้ปกครองสองคนเด็กคนหนึ่งเกิดขึ้น”

rebase

  • “ ให้การเปลี่ยนแปลงของสาขาหลัก (ไม่ว่าชื่อจะเป็นอะไร) กับสาขาคุณลักษณะของฉัน ทำเช่นนั้นโดยการแกล้งทำเป็นงานของฉันเริ่มต้นในภายหลังอันที่จริงเกี่ยวกับสถานะปัจจุบันของสาขาหลัก”
  • “ เขียนประวัติศาสตร์การเปลี่ยนแปลงของฉันเพื่อสะท้อนสิ่งนั้น” (จำเป็นต้องบังคับให้กดพวกเขาเพราะการกำหนดเวอร์ชันตามปกติเป็นเรื่องเกี่ยวกับการไม่ยุ่งเกี่ยวกับประวัติที่ได้รับ)
  • “ เป็นไปได้ - หากการเปลี่ยนแปลงที่ฉันทำไปมีส่วนเกี่ยวข้องกับงานของฉัน - ประวัติจริง ๆ แล้วจะไม่เปลี่ยนแปลงมากนักถ้าฉันดูความมุ่งมั่นของฉันแตกต่างจากความแตกต่าง (คุณอาจคิดถึง 'แพตช์') "

สรุป:เมื่อเป็นไปได้การลดระดับจะดีกว่าเสมอ ทำให้การรวมเข้ากับสาขาหลักง่ายขึ้น

เพราะ? ➝ทำงานคุณลักษณะของคุณสามารถนำเสนอเป็นหนึ่งใหญ่ 'แพทช์ไฟล์' (aka diff) ในส่วนที่เกี่ยวกับสาขาหลักไม่ต้อง 'อธิบาย' พ่อแม่หลายอย่างน้อยสองมาจากการผสาน แต่มีแนวโน้มมากถ้ามี มีหลายอย่างรวมกัน ต่างจากการผสานการรีบาวด์หลายครั้งจะไม่เพิ่มขึ้น (อีกหนึ่งบวกใหญ่)


18

Git rebase นั้นใกล้กับการรวม ความแตกต่างในการ rebase คือ:

  • ความมุ่งมั่นในท้องถิ่นจะถูกลบชั่วคราวจากสาขา
  • รัน git pull
  • แทรกทุกความมุ่งมั่นในท้องถิ่นของคุณ

นั่นหมายความว่าการกระทำในพื้นที่ของคุณทั้งหมดจะถูกย้ายไปยังจุดสิ้นสุดหลังจากการส่งข้อมูลระยะไกลทั้งหมด หากคุณมีข้อขัดแย้งผสานคุณต้องแก้ไขด้วย


7

เพื่อให้เข้าใจง่ายสามารถดูรูปของฉันได้

Rebase จะเปลี่ยนการแฮชเพื่อที่ว่าหากคุณต้องการหลีกเลี่ยงความขัดแย้งมาก ๆ ให้ใช้ rebase เมื่อสาขานั้นเสร็จสมบูรณ์ / เสถียร

ป้อนคำอธิบายรูปภาพที่นี่


0

ฉันพบบทความหนึ่งที่น่าสนใจจริงๆเกี่ยวกับ git rebase vs mergeคิดถึงการแบ่งปันที่นี่

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