เมื่อใดจึงแนะนำให้ใช้ Git rebase vs. Git merge?
ฉันยังต้องรวมหลังจากการรีบูตที่ประสบความสำเร็จหรือไม่?
เมื่อใดจึงแนะนำให้ใช้ Git rebase vs. Git merge?
ฉันยังต้องรวมหลังจากการรีบูตที่ประสบความสำเร็จหรือไม่?
คำตอบ:
ดังนั้นเมื่อไหร่ที่คุณจะใช้อันใดอันหนึ่ง?
init
repo ใหม่ไฟล์และadd
commit
ชำระเงินสาขาคุณลักษณะใหม่ ( checkout -b feature
.) เปลี่ยนไฟล์ข้อความกระทำและทำซ้ำเพื่อให้มีสองกระทำใหม่ในสาขาคุณสมบัติ แล้วและcheckout master
merge feature
ในlog
ฉันเห็นความมุ่งมั่นเริ่มต้นของฉันตามหลักแล้วตามด้วยสองสิ่งที่รวมเข้ากับคุณลักษณะ หากคุณmerge --squash feature
มีการรวมคุณสมบัติเข้ากับมาสเตอร์ แต่ไม่ได้ทำดังนั้นการมอบหมายใหม่บนมาสเตอร์จะเป็นสิ่งที่คุณทำเอง
มันง่ายมาก ด้วย rebase คุณบอกว่าจะใช้สาขาอื่นเป็นฐานใหม่สำหรับการทำงานของคุณ
ตัวอย่างเช่นถ้าคุณมีสาขาmaster
คุณจะสร้างสาขาเพื่อนำคุณสมบัติใหม่มาใช้และบอกว่าคุณตั้งชื่อcool-feature
สาขานั้นแน่นอนว่าสาขาหลักนั้นเป็นฐานสำหรับคุณลักษณะใหม่ของคุณ
ในตอนนี้คุณต้องการเพิ่มฟีเจอร์ใหม่ที่คุณนำไปใช้ในmaster
สาขา คุณสามารถเปลี่ยนเป็นmaster
และผสานcool-feature
สาขา:
$ git checkout master
$ git merge cool-feature
แต่วิธีนี้มีการเพิ่มการกระทำหลอกตาแบบใหม่ หากคุณต้องการหลีกเลี่ยงประวัติสปาเก็ตตี้คุณสามารถทำการrebase ได้ :
$ git checkout cool-feature
$ git rebase master
แล้วรวมมันเข้า master
:
$ git checkout master
$ git merge cool-feature
คราวนี้เนื่องจากหัวข้อกระทู้มีความมุ่งมั่นของมาสเตอร์ที่เหมือนกันบวกกับการกระทำที่มีคุณสมบัติใหม่การรวมจะเป็นเพียงการส่งต่อที่รวดเร็ว
but this way a new dummy commit is added, if you want to avoid spaghetti-history
- มันแย่ขนาดไหน?
Sean Schofield
ใส่ไว้ในความคิดเห็น: "Rebase ก็ดีเพราะเมื่อคุณรวมสิ่งต่างๆเข้าด้วยกันในที่สุด (ซึ่งเป็นเรื่องเล็กน้อยตามที่อธิบายไว้แล้ว) คุณได้นั่งอยู่ที่" บนสุด "ของประวัติศาสตร์ของคุณ โครงการที่อาจมีการเขียนคุณสมบัติ แต่รวมหลายสัปดาห์ต่อมาคุณไม่ต้องการรวมพวกมันเข้ากับนายเพราะพวกเขาได้ "ยัด" เข้าไปในทางกลับในประวัติศาสตร์โดยส่วนตัวแล้วฉันชอบที่จะทำบันทึกคอมไพล์และดู ฟีเจอร์ล่าสุดที่อยู่ด้านบน "ด้านบน" โปรดทราบว่าวันที่ส่งมอบจะถูกเก็บไว้ - การรีบูตจะไม่เปลี่ยนข้อมูลนั้น "
merge
, rebase
, fast-forward
ฯลฯ ) จะหมายถึงกิจวัตรที่เฉพาะเจาะจงของชี้นำวัฏจักรกราฟ พวกเขากลายเป็นเรื่องง่ายที่จะให้เหตุผลเกี่ยวกับแบบจำลองทางจิตในใจ
เพื่อเติมเต็มคำตอบของตัวเองที่กล่าวถึงโดย TSamper ,
การ rebase นั้นมักจะเป็นความคิดที่ดีที่จะทำก่อนที่จะทำการผสานเพราะความคิดคือการที่คุณผสานY
การทำงานของสาขาB
ที่คุณจะรวมเข้าด้วยกันในสาขาของคุณ
แต่อีกครั้งก่อนที่จะรวมคุณแก้ไขข้อขัดแย้งใด ๆ ในสาขาของคุณ (เช่น: "rebase" เช่นเดียวกับใน "เล่นซ้ำงานของฉันในสาขาของฉันเริ่มต้นจากจุดล่าสุดจากสาขาB
)
หากทำอย่างถูกต้องผสานที่สาขาจาก สาขาB
สามารถกรอไปข้างหน้า
การรวมกันจะส่งผลกระทบโดยตรงต่อสาขาปลายทางB
ซึ่งหมายถึงการรวมที่ดีกว่านั้นไม่สำคัญมิฉะนั้นสาขาB
อาจจะต้องกลับไปสู่สถานะที่มั่นคง (เวลาที่คุณแก้ไขข้อขัดแย้งทั้งหมด)
เป็นจุดรวมของการรีบูตหรือไม่
ในกรณีที่ฉันอธิบายฉัน rebase B
บนสาขาของฉันเพียงเพื่อมีโอกาส replay งานของฉันจากจุดล่าสุดจากB
แต่ในขณะที่อยู่ในสาขาของฉัน
ในกรณีนี้จำเป็นต้องมีการผสานเพื่อนำงาน "replayed" ของฉันไปB
ใช้
สถานการณ์อื่น ๆ (ซึ่งอธิบายไว้ใน Git Ready ) คือการนำงานของคุณโดยตรงB
ผ่านการรีบูต (ซึ่งเป็นการประหยัดค่าคอมมิชชันทั้งหมดของคุณหรือให้โอกาสในการสั่งซื้อใหม่ผ่านการรีบูตแบบโต้ตอบ)
ในกรณีนั้น (ที่คุณรีบูตในขณะที่อยู่ในสาขา B) คุณพูดถูก: ไม่จำเป็นต้องรวมอีกต่อไป:
ต้นไม้ Git เป็นค่าเริ่มต้นเมื่อเรายังไม่ได้รวมหรือไม่ได้รีบาวด์
เราได้รับจากการรีบูต:
สถานการณ์ที่สองนั้นเป็นเรื่องเกี่ยวกับ: ฉันจะนำคุณลักษณะใหม่กลับมาเป็นหลักได้อย่างไร
จุดของฉันโดยการอธิบายสถานการณ์จำลองการรีบูตครั้งแรกคือเพื่อเตือนทุกคนว่าการรีบูตสามารถใช้เป็นขั้นตอนเบื้องต้นในการนั้นได้ (นั่นคือ "ได้รับคุณลักษณะใหม่กลับสู่ต้นแบบ")
คุณสามารถใช้ rebase แรกนำต้นแบบ "ใน" สาขาใหม่คุณลักษณะ: rebase จะเล่นใหม่กระทำคุณลักษณะจากแต่ยังคงอยู่ในสาขาใหม่คุณลักษณะที่มีประสิทธิภาพการย้ายสาขาของจุดเริ่มต้นจากเจ้านายเก่ามุ่งมั่นที่จะHEAD master
ที่ช่วยให้คุณสามารถแก้ไขข้อขัดแย้งใด ๆ ในสาขาของคุณ (หมายถึงแยกออกจากกันในขณะที่ช่วยให้ต้นแบบยังคงมีวิวัฒนาการในแบบคู่ขนานหากขั้นตอนการแก้ไขข้อขัดแย้งของคุณใช้เวลานานเกินไป)
จากนั้นคุณสามารถสลับไปยังต้นแบบและผสาน(หรือลดลงหากคุณต้องการเก็บรักษาความมุ่งมั่นที่ทำไว้ในของคุณHEAD-master
new-feature
new-feature
master
new-feature
สาขา).
ดังนั้น:
master
สามารถดูเป็นสองวิธีที่จะนำเข้าทำงานในการพูดที่หากคุณมีข้อสงสัยให้ใช้การผสาน
ข้อแตกต่างระหว่าง rebase และ merge คือ:
ดังนั้นคำตอบสั้น ๆ คือเลือก rebase หรือผสานตามสิ่งที่คุณต้องการให้ประวัติของคุณเป็นเช่นนั้น
มีปัจจัยบางประการที่คุณควรพิจารณาเมื่อเลือกการทำงานที่จะใช้
ถ้าใช่อย่ารีบูท rebase ทำลายสาขาและนักพัฒนาเหล่านั้นจะได้หัก / git pull --rebase
เก็บที่ไม่สอดคล้องกันจนกว่าพวกเขาจะใช้ นี่เป็นวิธีที่ดีในการทำให้เสียผู้พัฒนารายอื่นอย่างรวดเร็ว
Rebase เป็นการปฏิบัติการทำลายล้าง ซึ่งหมายความว่าหากคุณใช้งานไม่ถูกต้องคุณอาจสูญเสียงานที่มอบหมายและ / หรือทำลายความสอดคล้องของคลังเก็บของผู้พัฒนารายอื่น
ฉันได้ทำงานกับทีมที่นักพัฒนาซอฟต์แวร์ทุกคนมาจากช่วงเวลาที่ บริษัท สามารถให้พนักงานที่ทุ่มเทเพื่อจัดการกับการรวมสาขาและการควบรวมกิจการ นักพัฒนาเหล่านั้นไม่ค่อยรู้อะไรเกี่ยวกับ Git และไม่ต้องการรู้อะไรมากมาย ในทีมเหล่านี้ฉันจะไม่เสี่ยงที่จะแนะนำการรีบูตด้วยเหตุผลใดก็ตาม
บางทีมใช้โมเดลสาขาต่อคุณลักษณะที่แต่ละสาขาแสดงคุณลักษณะ (หรือแก้ไขข้อผิดพลาดหรือคุณสมบัติย่อย ฯลฯ ) ในรุ่นนี้สาขาจะช่วยระบุชุดของการผูกพันที่เกี่ยวข้อง ตัวอย่างเช่นหนึ่งสามารถย้อนกลับคุณสมบัติอย่างรวดเร็วโดยการคืนค่าการผสานของสาขานั้น (เพื่อความยุติธรรมนี่เป็นการดำเนินการที่หายาก) หรือแตกต่างคุณลักษณะโดยการเปรียบเทียบสองสาขา (ทั่วไป) การ Rebase จะทำลายกิ่งไม้และสิ่งนี้จะไม่ตรงไปตรงมา
ฉันยังทำงานกับทีมที่ใช้โมเดลสาขาต่อผู้พัฒนา (เราทุกคนอยู่ที่นั่น) ในกรณีนี้สาขาเองไม่ได้นำเสนอข้อมูลเพิ่มเติมใด ๆ (กระทำได้แล้วมีผู้เขียน) จะไม่มีอันตรายในการรีบูต
การคืนค่า (ในการเลิกทำ) การ rebase นั้นยากมากและ / หรือเป็นไปไม่ได้ (หากการ rebase มีข้อขัดแย้ง) เปรียบเทียบกับการคืนค่าการผสาน หากคุณคิดว่ามีโอกาสคุณจะต้องเปลี่ยนกลับไปใช้การรวม
การดำเนินงาน rebase git pull --rebase
จะต้องมีการดึงกับที่สอดคล้องกัน หากคุณทำงานด้วยตัวเองคุณอาจจำได้ว่าควรใช้งานอะไรในเวลาที่เหมาะสม หากคุณกำลังทำงานกับทีมสิ่งนี้จะยากมากในการประสานงาน นี่คือเหตุผลที่เวิร์กโฟลว์การรีบูตส่วนใหญ่แนะนำให้ใช้ rebase สำหรับการรวมทั้งหมด (และgit pull --rebase
การดึงทั้งหมด)
สมมติว่าคุณมีการผสานดังต่อไปนี้:
B -- C
/ \
A--------D
บางคนจะกล่าวว่าการผสาน "ทำลาย" ประวัติการกระทำเพราะถ้าคุณดูที่บันทึกของสาขาหลักเท่านั้น (A - D) คุณจะพลาดข้อความการกระทำที่สำคัญที่มีอยู่ใน B และ C
ถ้าเรื่องนี้เป็นความจริงที่เราจะได้มีคำถามเช่นนี้ โดยทั่วไปคุณจะเห็น B และ C เว้นแต่คุณจะขอให้ไม่เห็นพวกเขา (โดยใช้ --first-parent) มันง่ายมากที่จะลองด้วยตัวคุณเอง
วิธีการทั้งสองผสานกันแตกต่างกัน แต่ไม่ชัดเจนว่าวิธีหนึ่งดีกว่าวิธีอื่นเสมอและอาจขึ้นอยู่กับเวิร์กโฟลว์นักพัฒนาซอฟต์แวร์ ตัวอย่างเช่นหากนักพัฒนามีแนวโน้มที่จะกระทำอย่างสม่ำเสมอ (เช่นพวกเขาอาจกระทำวันละสองครั้งขณะที่พวกเขาเปลี่ยนจากการทำงานไปที่บ้าน) จากนั้นอาจมีข้อผูกพันมากมายสำหรับสาขาที่กำหนด การกระทำเหล่านั้นจำนวนมากอาจไม่ดูเหมือนผลิตภัณฑ์ขั้นสุดท้าย (ฉันมักจะปรับวิธีการของฉันอีกครั้งหนึ่งหรือสองครั้งต่อคุณสมบัติ) หากมีคนอื่นกำลังทำงานในส่วนของรหัสที่เกี่ยวข้องและพวกเขาพยายามที่จะลดการเปลี่ยนแปลงของฉันมันอาจเป็นการดำเนินการที่ค่อนข้างน่าเบื่อ
หากคุณต้องการนามแฝงrm
ถึงrm -rf
"ประหยัดเวลา" บางทีการรีบูตอาจเหมาะสำหรับคุณ
ฉันคิดเสมอว่าสักวันฉันจะเจอสถานการณ์ที่การรีบูต Git เป็นเครื่องมือที่ยอดเยี่ยมที่แก้ปัญหาได้ เหมือนที่ฉันคิดว่าฉันจะเจอสถานการณ์ที่ Git reflog เป็นเครื่องมือที่ยอดเยี่ยมที่ช่วยแก้ปัญหาของฉัน ฉันทำงานกับ Git มาห้าปีแล้ว มันไม่ได้เกิดขึ้น
ประวัติที่ยุ่งเหยิงไม่เคยเป็นปัญหาสำหรับฉันเลย ฉันไม่เคยอ่านประวัติการกระทำของฉันเหมือนนิยายที่น่าตื่นเต้น เวลาส่วนใหญ่ที่ฉันต้องการประวัติฉันจะใช้ตำหนิ Git หรือ Gis bisect ต่อไป ในกรณีดังกล่าวการมีการรวมการกระทำนั้นมีประโยชน์กับฉันจริง ๆ เพราะถ้าการรวมที่นำเสนอปัญหานั่นเป็นข้อมูลที่มีความหมายสำหรับฉัน
ฉันรู้สึกผูกพันที่จะต้องพูดถึงว่าฉันได้ลดการใช้ rebase เป็นการส่วนตัวถึงแม้ว่าคำแนะนำทั่วไปของฉันจะยังคงอยู่ เมื่อไม่นานมานี้ฉันมีปฏิสัมพันธ์กับโครงการวัสดุ Angular 2มาก พวกเขาใช้การ rebase เพื่อรักษาประวัติการกระทำที่สะอาดมาก สิ่งนี้ทำให้ฉันเห็นได้อย่างง่ายดายว่าการกระทำใดที่แก้ไขข้อบกพร่องที่กำหนดไว้และการกระทำนั้นรวมอยู่ในการเปิดตัวหรือไม่ มันทำหน้าที่เป็นตัวอย่างที่ดีของการใช้ rebase อย่างถูกต้อง
คำตอบมากมายที่นี่บอกว่าการรวมกันจะเปลี่ยนความมุ่งมั่นทั้งหมดของคุณเป็นหนึ่งเดียวดังนั้นจึงแนะนำให้ใช้ rebase เพื่อรักษาความมุ่งมั่นของคุณ สิ่งนี้ไม่ถูกต้อง และเป็นความคิดที่ไม่ดีถ้าคุณมีการผลักดันกระทำของคุณแล้ว
การผสานไม่ทำให้การกระทำของคุณหมดไป ผสานรักษาประวัติศาสตร์! (ดูที่ gitk) Rebase เขียนประวัติศาสตร์ใหม่ซึ่งเป็นสิ่งที่แย่หลังจากที่คุณผลักมัน
ใช้การผสาน - ไม่ใช่การรีบูตเมื่อใดก็ตามที่คุณผลักแล้ว
นี่คือ Linus '(ผู้แต่ง Git) รับหน้าที่ (ปัจจุบันโฮสต์ในบล็อกของฉันเองซึ่งกู้คืนโดย Wayback Machine ) มันเป็นการอ่านที่ดีจริงๆ
หรือคุณสามารถอ่านแนวคิดเดียวกันของฉันด้านล่าง
การสยบสาขาบนมาสเตอร์:
ในทางตรงกันข้ามการรวมสาขาหัวข้อเป็นหลัก:
TLDR: มันขึ้นอยู่กับสิ่งที่สำคัญที่สุด - ประวัติที่เป็นระเบียบหรือเป็นตัวแทนที่แท้จริงของลำดับการพัฒนา
หากประวัติที่เป็นระเบียบเป็นสิ่งสำคัญที่สุดคุณจะต้องทำการรีบูตก่อนแล้วจึงรวมการเปลี่ยนแปลงของคุณดังนั้นจึงเป็นที่ชัดเจนว่ารหัสใหม่คืออะไร หากคุณผลักสาขาของคุณไปแล้วอย่ารีบูตเว้นแต่คุณจะสามารถจัดการกับผลที่ตามมา
หากการแสดงลำดับที่แท้จริงเป็นสิ่งสำคัญที่สุดคุณจะรวมโดยไม่ต้องรีบูต
ผสานหมายถึง: สร้างคอมมิทใหม่ที่รวมการเปลี่ยนแปลงของฉันเข้ากับปลายทาง หมายเหตุ: การคอมมิชชันใหม่นี้จะมีผู้ปกครองสองคน - การคอมมิชชันล่าสุดจากสตริงการคอมมิทของคุณและการคอมมิชชันล่าสุดของสาขาอื่นที่คุณกำลังรวม
Rebase หมายถึง: สร้างคอมมิทใหม่ทั้งหมดโดยใช้คอมมิทชุดปัจจุบันของฉันเป็นคำใบ้ กล่าวอีกนัยหนึ่งคำนวณว่าการเปลี่ยนแปลงของฉันจะเป็นอย่างไรถ้าฉันเริ่มทำให้พวกเขาเปลี่ยนจากจุดที่ฉันเริ่มทำไป หลังจากการรีบูตดังนั้นคุณอาจต้องทดสอบการเปลี่ยนแปลงของคุณอีกครั้งและในระหว่างการรีบูตคุณอาจมีข้อขัดแย้งเล็กน้อย
เมื่อได้รับสิ่งนี้ทำไมคุณถึงลดระดับ เพียงเพื่อให้ประวัติการพัฒนาชัดเจน สมมติว่าคุณกำลังทำงานกับคุณสมบัติ X และเมื่อคุณทำเสร็จแล้วคุณจะรวมการเปลี่ยนแปลงของคุณในตอนนี้ปลายทางจะมีความมุ่งมั่นเดียวที่จะพูดอะไรบางอย่างตามแนวของ "คุณสมบัติเพิ่ม X" ตอนนี้แทนที่จะรวมหากคุณ rebased แล้วผสานประวัติศาสตร์การพัฒนาปลายทางจะมีความมุ่งมั่นของแต่ละบุคคลในความก้าวหน้าตรรกะเดียว ทำให้การตรวจสอบการเปลี่ยนแปลงในภายหลังนั้นง่ายขึ้นมาก ลองจินตนาการว่าคุณจะพบว่ามันยากแค่ไหนในการตรวจสอบประวัติการพัฒนาหากนักพัฒนา 50 คนรวมคุณสมบัติที่หลากหลายตลอดเวลา
ที่กล่าวว่าหากคุณผลักสาขาที่คุณทำงานอยู่เหนือน้ำคุณไม่ควรทำการ rebase แต่ให้รวมกันแทน สำหรับสาขาที่ยังไม่ได้รับการผลักดันอัปสตรีม, รีบูต, ทดสอบและรวม
อีกครั้งที่คุณอาจต้องการรีบูตคือเมื่อคุณต้องการกำจัดการผูกมัดจากสาขาของคุณก่อนที่จะผลักดันอัปสตรีม ตัวอย่างเช่น: คอมมิทที่แนะนำโค้ดการดีบักบางส่วนก่อนหน้าและคอมมิชชันอื่น ๆ เพิ่มเติมเกี่ยวกับการล้างโค้ดนั้น วิธีเดียวในการทำเช่นนี้คือการดำเนินการ rebase เชิงโต้ตอบ:git rebase -i <branch/commit/tag>
อัปเดต: คุณต้องการใช้ rebase เมื่อคุณใช้ Git เพื่อเชื่อมต่อกับระบบควบคุมเวอร์ชันที่ไม่สนับสนุนประวัติที่ไม่ใช่เชิงเส้น ( ตัวอย่างเช่นการโค่นล้ม ) เมื่อใช้สะพาน git-svn เป็นสิ่งสำคัญมากที่การเปลี่ยนแปลงที่คุณรวมกลับไปที่การโค่นล้มเป็นรายการลำดับการเปลี่ยนแปลงที่ด้านบนของการเปลี่ยนแปลงล่าสุดในลำตัว มีเพียงสองวิธีในการทำเช่นนั้น: (1) สร้างการเปลี่ยนแปลงใหม่ด้วยตนเองและ (2) การใช้คำสั่ง rebase ซึ่งเร็วกว่ามาก
อัปเดต 2: อีกวิธีหนึ่งในการคิดว่าการคืนเงินคือการเปิดใช้งานการเรียงลำดับการแมปจากสไตล์การพัฒนาของคุณไปจนถึงสไตล์ที่ยอมรับในที่เก็บข้อมูลที่คุณยอมรับ สมมติว่าคุณชอบที่จะกระทำในชิ้นเล็ก ๆ คุณมีหนึ่งความมุ่งมั่นที่จะแก้ไขการพิมพ์ผิดหนึ่งคนมุ่งมั่นที่จะกำจัดรหัสที่ไม่ได้ใช้และอื่น ๆ เมื่อคุณทำสิ่งที่คุณต้องทำเสร็จแล้ว ตอนนี้สมมติว่าพื้นที่เก็บข้อมูลที่คุณมุ่งมั่นที่จะส่งเสริมการกระทำที่มีขนาดใหญ่ดังนั้นสำหรับงานที่คุณกำลังทำใครจะคาดหวังหนึ่งหรือสองคนมุ่งมั่น คุณจะใช้สายของคุณมุ่งมั่นและบีบอัดให้เป็นสิ่งที่คาดหวังได้อย่างไร คุณจะใช้ rebase เชิงโต้ตอบและสควอชเล็ก ๆ ของคุณมุ่งมั่นเป็นชิ้นใหญ่น้อย สิ่งนี้เป็นจริงถ้าต้องการย้อนกลับ - ถ้าสไตล์ของคุณมีขนาดใหญ่ แต่พื้นที่เก็บข้อมูลเรียกร้องสตริงที่มีขนาดเล็ก คุณจะใช้ rebase เพื่อทำเช่นนั้น หากคุณได้ผสานแทนตอนนี้คุณได้กราฟต์สไตล์การคอมมิตของคุณลงในที่เก็บหลัก หากมีนักพัฒนาจำนวนมากคุณสามารถจินตนาการได้ว่ามันจะยากเพียงใดในการติดตามประวัติด้วยสไตล์การคอมมิทที่แตกต่างกันหลายครั้ง
ปรับปรุง 3: Does one still need to merge after a successful rebase?
ใช่คุณทำ เหตุผลก็คือการคืนเงินเป็นหลักเกี่ยวข้องกับ "การเปลี่ยนแปลง" ของการกระทำ ดังที่ฉันได้กล่าวไว้ข้างต้นคอมมิชชันเหล่านี้ถูกคำนวณ แต่ถ้าคุณมี 14 คอมมิตจากการแตกแขนงจากนั้นสมมติว่าไม่มีอะไรผิดปกติกับการรีบูทของคุณคุณจะได้ 14 คอมมิตข้างหน้า rebase เสร็จแล้ว คุณมีสาขาก่อนการลดระดับ คุณจะมีสาขาที่มีความยาวเท่ากันหลังจากนั้น คุณยังคงต้องรวมก่อนที่จะเผยแพร่การเปลี่ยนแปลงของคุณ กล่าวอีกนัยหนึ่ง rebase หลายครั้งตามที่คุณต้องการ (อีกครั้งเฉพาะในกรณีที่คุณไม่ได้ผลักดันการเปลี่ยนแปลงของคุณต้นน้ำ) รวมหลังจากคุณรีบูตเท่านั้น
git merge
สนับสนุน--no-ff
ตัวเลือกที่บังคับให้ทำการรวมคำสั่ง
ในขณะที่การรวมกันเป็นวิธีที่ง่ายที่สุดและพบได้บ่อยที่สุดในการรวมการเปลี่ยนแปลง แต่ไม่ใช่วิธีเดียว: การRebaseเป็นวิธีการรวมทางเลือกอื่น
เข้าใจการผสานดีขึ้นเล็กน้อย
เมื่อ Git ทำการผสานมันจะค้นหาการกระทำที่สาม:
กรอไปข้างหน้าหรือผสาน
ในกรณีที่ง่ายมากหนึ่งในสองสาขานั้นไม่มีความมุ่งมั่นใหม่ใด ๆ ตั้งแต่เกิดการแตกกิ่ง - การกระทำล่าสุดยังคงเป็นบรรพบุรุษร่วมกัน
ในกรณีนี้การทำการรวมนั้นง่ายมาก: Git สามารถเพิ่มการกระทำทั้งหมดของสาขาอื่นที่อยู่ด้านบนของบรรพบุรุษที่กระทำร่วมกัน ใน Git การรวมรูปแบบที่ง่ายที่สุดนี้เรียกว่าการผสาน "กรอไปข้างหน้า" ทั้งสองสาขานั้นแบ่งปันประวัติเดียวกันที่แน่นอน
อย่างไรก็ตามในหลายกรณีทั้งสองสาขาต่างก็ก้าวไปข้างหน้าเป็นรายบุคคล
ในการรวมเข้าด้วยกัน Git จะต้องสร้างการคอมมิทใหม่ที่มีความแตกต่างระหว่างการคอมมิทนั่นคือการรวมการคอมมิท
ความมุ่งมั่นของมนุษย์และการรวมความมุ่งมั่น
โดยปกติความมุ่งมั่นนั้นถูกสร้างขึ้นอย่างรอบคอบโดยมนุษย์ เป็นหน่วยที่มีความหมายซึ่งห่อหุ้มการเปลี่ยนแปลงที่เกี่ยวข้องเท่านั้นและใส่หมายเหตุประกอบไว้ด้วยความคิดเห็น
การคอมมิชชันการผสานแตกต่างกันเล็กน้อย: แทนที่จะสร้างโดยนักพัฒนามันจะถูกสร้างขึ้นโดยอัตโนมัติโดย Git และแทนที่จะห่อชุดของการเปลี่ยนแปลงที่เกี่ยวข้องวัตถุประสงค์ของมันคือการเชื่อมต่อสองสาขาเหมือนปม หากคุณต้องการที่จะเข้าใจการดำเนินการผสานในภายหลังคุณจะต้องดูประวัติของทั้งสองสาขาและกราฟการกระทำที่สอดคล้องกัน
การรวมเข้ากับ Rebase
บางคนชอบที่จะไปโดยไม่มีการผสานอัตโนมัติเช่นนั้น แต่พวกเขาต้องการให้ประวัติของโครงการดูราวกับว่ามันมีวิวัฒนาการในแนวเส้นตรงเส้นเดียว ไม่มีข้อบ่งชี้ว่ามันถูกแบ่งออกเป็นหลายสาขาในบางจุด
เรามาดูการดำเนินการ rebase ทีละขั้นตอน สถานการณ์เหมือนกันในตัวอย่างก่อนหน้านี้: เราต้องการรวมการเปลี่ยนแปลงจาก branch-B เข้ากับ branch-A แต่ตอนนี้โดยใช้ rebase
เราจะทำสิ่งนี้ในสามขั้นตอน
git rebase branch-A // Synchronises the history with branch-A
git checkout branch-A // Change the current branch to branch-A
git merge branch-B // Merge/take the changes from branch-B to branch-A
อันดับแรก Git จะ "เลิกทำ" ทั้งหมดที่ทำกับสาขา A ที่เกิดขึ้นหลังจากที่สายเริ่มแยกออก (หลังจากบรรพบุรุษร่วมกันกระทำ) อย่างไรก็ตามแน่นอนว่ามันจะไม่ทิ้งพวกเขา แต่คุณสามารถคิดได้ว่าพวกเขาจะถูก "ช่วยให้รอด" ชั่วคราว
ต่อไปจะใช้ข้อผูกพันจาก branch-B ที่เราต้องการรวม ณ จุดนี้กิ่งทั้งสองมีลักษณะเหมือนกันทุกประการ
ในขั้นตอนสุดท้ายการคอมมิชชันใหม่ใน branch-A จะถูกนำมาใช้ใหม่ - แต่ในตำแหน่งใหม่ที่ด้านบนของคอมมิทคอมบิวชั่นจาก Branch-B
ผลลัพธ์ดูเหมือนว่าการพัฒนาจะเกิดขึ้นเป็นเส้นตรง แทนที่จะรวมการคอมมิชชันที่มีการเปลี่ยนแปลงทั้งหมดที่รวมไว้โครงสร้างการคอมมิชชันดั้งเดิมจะถูกเก็บรักษาไว้
ในที่สุดคุณจะได้สาขาที่สะอาด สาขา-Aไม่มีกระทำที่ไม่พึงประสงค์และสร้างขึ้นโดยอัตโนมัติ
หมายเหตุ:นำมาจากที่น่ากลัวโพสต์git-tower
โดย ข้อเสียของrebase
ยังดีอ่านในโพสต์เดียวกัน
ก่อนที่จะรวม / รีบูต:
A <- B <- C [master]
^
\
D <- E [branch]
หลังgit merge master
:
A <- B <- C
^ ^
\ \
D <- E <- F
หลังgit rebase master
:
A <- B <- C <- D' <- E'
(A, B, C, D, E และ F เป็นข้อผูกมัด)
ตัวอย่างเช่นนี้และอีกข้อมูลที่แสดงมากขึ้นเกี่ยวกับ Git สามารถพบได้ในGit พื้นฐานการสอน
ประโยคนี้ทำให้เข้าใจ:
โดยทั่วไปวิธีที่ดีที่สุดของโลกทั้งสองคือการลดการเปลี่ยนแปลงในท้องถิ่นที่คุณทำ แต่ยังไม่ได้แชร์ก่อนที่คุณจะผลักดันพวกเขาเพื่อทำความสะอาดเรื่องราวของคุณ .
คำตอบนี้เน้นไปที่Git Flow เป็นวงกว้าง ตารางถูกสร้างด้วยASCII Table Generator ที่ดีและแผนผังประวัติด้วยคำสั่งที่ยอดเยี่ยมนี้ ( aliased as git lg
):
git log --graph --abbrev-commit --decorate --date=format:'%Y-%m-%d %H:%M:%S' --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%ad%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)'
ตารางอยู่ในลำดับย้อนกลับเพื่อให้สอดคล้องกับต้นไม้ประวัติศาสตร์มากขึ้น ดูความแตกต่างระหว่างgit merge
และgit merge --no-ff
ก่อน (คุณมักจะต้องการใช้git merge --no-ff
เพราะมันทำให้ประวัติของคุณดูใกล้เคียงกับความเป็นจริง):
git merge
คำสั่ง:
Time Branch "develop" Branch "features/foo"
------- ------------------------------ -------------------------------
15:04 git merge features/foo
15:03 git commit -m "Third commit"
15:02 git commit -m "Second commit"
15:01 git checkout -b features/foo
15:00 git commit -m "First commit"
ผลลัพธ์:
* 142a74a - YYYY-MM-DD 15:03:00 (XX minutes ago) (HEAD -> develop, features/foo)
| Third commit - Christophe
* 00d848c - YYYY-MM-DD 15:02:00 (XX minutes ago)
| Second commit - Christophe
* 298e9c5 - YYYY-MM-DD 15:00:00 (XX minutes ago)
First commit - Christophe
git merge --no-ff
คำสั่ง:
Time Branch "develop" Branch "features/foo"
------- -------------------------------- -------------------------------
15:04 git merge --no-ff features/foo
15:03 git commit -m "Third commit"
15:02 git commit -m "Second commit"
15:01 git checkout -b features/foo
15:00 git commit -m "First commit"
ผลลัพธ์:
* 1140d8c - YYYY-MM-DD 15:04:00 (XX minutes ago) (HEAD -> develop)
|\ Merge branch 'features/foo' - Christophe
| * 69f4a7a - YYYY-MM-DD 15:03:00 (XX minutes ago) (features/foo)
| | Third commit - Christophe
| * 2973183 - YYYY-MM-DD 15:02:00 (XX minutes ago)
|/ Second commit - Christophe
* c173472 - YYYY-MM-DD 15:00:00 (XX minutes ago)
First commit - Christophe
git merge
VS git rebase
จุดแรก: เสมอผสานคุณสมบัติเข้าไปพัฒนาไม่เคย rebase พัฒนาจากคุณสมบัติ นี่เป็นผลสืบเนื่องจากกฎทองของการคืนเงิน :
กฎทองของการ
git rebase
คือการไม่ใช้มันในที่สาธารณะสาขา
อย่ารีบูทสิ่งที่คุณผลักไป
ผมเองจะเพิ่ม: เว้นแต่จะเป็นสาขาคุณลักษณะและคุณและทีมงานของคุณมีความตระหนักถึงผลกระทบ
ดังนั้นคำถามของgit merge
vs git rebase
จะใช้กับสาขาคุณลักษณะเท่านั้น (ในตัวอย่างต่อไปนี้--no-ff
ถูกนำมาใช้เสมอเมื่อทำการผสาน) โปรดทราบว่าเนื่องจากฉันไม่แน่ใจว่ามีวิธีแก้ปัญหาที่ดีกว่า ( มีการโต้วาที ) ฉันจะให้เฉพาะคำสั่งที่ทำงานทั้งสอง ในกรณีของฉันฉันชอบที่จะใช้git rebase
เพราะสร้างต้นไม้ประวัติที่ดีกว่า :)
git merge
คำสั่ง:
Time Branch "develop" Branch "features/foo" Branch "features/bar"
------- -------------------------------- ------------------------------- --------------------------------
15:10 git merge --no-ff features/bar
15:09 git merge --no-ff features/foo
15:08 git commit -m "Sixth commit"
15:07 git merge --no-ff features/foo
15:06 git commit -m "Fifth commit"
15:05 git commit -m "Fourth commit"
15:04 git commit -m "Third commit"
15:03 git commit -m "Second commit"
15:02 git checkout -b features/bar
15:01 git checkout -b features/foo
15:00 git commit -m "First commit"
ผลลัพธ์:
* c0a3b89 - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop)
|\ Merge branch 'features/bar' - Christophe
| * 37e933e - YYYY-MM-DD 15:08:00 (XX minutes ago) (features/bar)
| | Sixth commit - Christophe
| * eb5e657 - YYYY-MM-DD 15:07:00 (XX minutes ago)
| |\ Merge branch 'features/foo' into features/bar - Christophe
| * | 2e4086f - YYYY-MM-DD 15:06:00 (XX minutes ago)
| | | Fifth commit - Christophe
| * | 31e3a60 - YYYY-MM-DD 15:05:00 (XX minutes ago)
| | | Fourth commit - Christophe
* | | 98b439f - YYYY-MM-DD 15:09:00 (XX minutes ago)
|\ \ \ Merge branch 'features/foo' - Christophe
| |/ /
|/| /
| |/
| * 6579c9c - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo)
| | Third commit - Christophe
| * 3f41d96 - YYYY-MM-DD 15:03:00 (XX minutes ago)
|/ Second commit - Christophe
* 14edc68 - YYYY-MM-DD 15:00:00 (XX minutes ago)
First commit - Christophe
git rebase
คำสั่ง:
Time Branch "develop" Branch "features/foo" Branch "features/bar"
------- -------------------------------- ------------------------------- -------------------------------
15:10 git merge --no-ff features/bar
15:09 git merge --no-ff features/foo
15:08 git commit -m "Sixth commit"
15:07 git rebase features/foo
15:06 git commit -m "Fifth commit"
15:05 git commit -m "Fourth commit"
15:04 git commit -m "Third commit"
15:03 git commit -m "Second commit"
15:02 git checkout -b features/bar
15:01 git checkout -b features/foo
15:00 git commit -m "First commit"
ผลลัพธ์:
* 7a99663 - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop)
|\ Merge branch 'features/bar' - Christophe
| * 708347a - YYYY-MM-DD 15:08:00 (XX minutes ago) (features/bar)
| | Sixth commit - Christophe
| * 949ae73 - YYYY-MM-DD 15:06:00 (XX minutes ago)
| | Fifth commit - Christophe
| * 108b4c7 - YYYY-MM-DD 15:05:00 (XX minutes ago)
| | Fourth commit - Christophe
* | 189de99 - YYYY-MM-DD 15:09:00 (XX minutes ago)
|\ \ Merge branch 'features/foo' - Christophe
| |/
| * 26835a0 - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo)
| | Third commit - Christophe
| * a61dd08 - YYYY-MM-DD 15:03:00 (XX minutes ago)
|/ Second commit - Christophe
* ae6f5fc - YYYY-MM-DD 15:00:00 (XX minutes ago)
First commit - Christophe
develop
ไปยังสาขาฟีเจอร์git merge
คำสั่ง:
Time Branch "develop" Branch "features/foo" Branch "features/bar"
------- -------------------------------- ------------------------------- -------------------------------
15:10 git merge --no-ff features/bar
15:09 git commit -m "Sixth commit"
15:08 git merge --no-ff develop
15:07 git merge --no-ff features/foo
15:06 git commit -m "Fifth commit"
15:05 git commit -m "Fourth commit"
15:04 git commit -m "Third commit"
15:03 git commit -m "Second commit"
15:02 git checkout -b features/bar
15:01 git checkout -b features/foo
15:00 git commit -m "First commit"
ผลลัพธ์:
* 9e6311a - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop)
|\ Merge branch 'features/bar' - Christophe
| * 3ce9128 - YYYY-MM-DD 15:09:00 (XX minutes ago) (features/bar)
| | Sixth commit - Christophe
| * d0cd244 - YYYY-MM-DD 15:08:00 (XX minutes ago)
| |\ Merge branch 'develop' into features/bar - Christophe
| |/
|/|
* | 5bd5f70 - YYYY-MM-DD 15:07:00 (XX minutes ago)
|\ \ Merge branch 'features/foo' - Christophe
| * | 4ef3853 - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo)
| | | Third commit - Christophe
| * | 3227253 - YYYY-MM-DD 15:03:00 (XX minutes ago)
|/ / Second commit - Christophe
| * b5543a2 - YYYY-MM-DD 15:06:00 (XX minutes ago)
| | Fifth commit - Christophe
| * 5e84b79 - YYYY-MM-DD 15:05:00 (XX minutes ago)
|/ Fourth commit - Christophe
* 2da6d8d - YYYY-MM-DD 15:00:00 (XX minutes ago)
First commit - Christophe
git rebase
คำสั่ง:
Time Branch "develop" Branch "features/foo" Branch "features/bar"
------- -------------------------------- ------------------------------- -------------------------------
15:10 git merge --no-ff features/bar
15:09 git commit -m "Sixth commit"
15:08 git rebase develop
15:07 git merge --no-ff features/foo
15:06 git commit -m "Fifth commit"
15:05 git commit -m "Fourth commit"
15:04 git commit -m "Third commit"
15:03 git commit -m "Second commit"
15:02 git checkout -b features/bar
15:01 git checkout -b features/foo
15:00 git commit -m "First commit"
ผลลัพธ์:
* b0f6752 - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop)
|\ Merge branch 'features/bar' - Christophe
| * 621ad5b - YYYY-MM-DD 15:09:00 (XX minutes ago) (features/bar)
| | Sixth commit - Christophe
| * 9cb1a16 - YYYY-MM-DD 15:06:00 (XX minutes ago)
| | Fifth commit - Christophe
| * b8ddd19 - YYYY-MM-DD 15:05:00 (XX minutes ago)
|/ Fourth commit - Christophe
* 856433e - YYYY-MM-DD 15:07:00 (XX minutes ago)
|\ Merge branch 'features/foo' - Christophe
| * 694ac81 - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo)
| | Third commit - Christophe
| * 5fd94d3 - YYYY-MM-DD 15:03:00 (XX minutes ago)
|/ Second commit - Christophe
* d01d589 - YYYY-MM-DD 15:00:00 (XX minutes ago)
First commit - Christophe
git cherry-pick
เมื่อคุณต้องการการคอมมิชชันที่เฉพาะเจาะจงgit cherry-pick
มันเป็นคำตอบที่ดี ( -x
ตัวเลือกต่อท้ายบรรทัดที่เขียนว่า " (เชอร์รี่ที่เลือกจากคอมมิชชัน ... ) " ไปยังเนื้อหาข้อความคอมมิชชันดั้งเดิมดังนั้นจึงเป็นความคิดที่ดีที่จะใช้git log <commit_sha1>
เพื่อดู มัน):
คำสั่ง:
Time Branch "develop" Branch "features/foo" Branch "features/bar"
------- -------------------------------- ------------------------------- -----------------------------------------
15:10 git merge --no-ff features/bar
15:09 git merge --no-ff features/foo
15:08 git commit -m "Sixth commit"
15:07 git cherry-pick -x <second_commit_sha1>
15:06 git commit -m "Fifth commit"
15:05 git commit -m "Fourth commit"
15:04 git commit -m "Third commit"
15:03 git commit -m "Second commit"
15:02 git checkout -b features/bar
15:01 git checkout -b features/foo
15:00 git commit -m "First commit"
ผลลัพธ์:
* 50839cd - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop)
|\ Merge branch 'features/bar' - Christophe
| * 0cda99f - YYYY-MM-DD 15:08:00 (XX minutes ago) (features/bar)
| | Sixth commit - Christophe
| * f7d6c47 - YYYY-MM-DD 15:03:00 (XX minutes ago)
| | Second commit - Christophe
| * dd7d05a - YYYY-MM-DD 15:06:00 (XX minutes ago)
| | Fifth commit - Christophe
| * d0d759b - YYYY-MM-DD 15:05:00 (XX minutes ago)
| | Fourth commit - Christophe
* | 1a397c5 - YYYY-MM-DD 15:09:00 (XX minutes ago)
|\ \ Merge branch 'features/foo' - Christophe
| |/
|/|
| * 0600a72 - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo)
| | Third commit - Christophe
| * f4c127a - YYYY-MM-DD 15:03:00 (XX minutes ago)
|/ Second commit - Christophe
* 0cf894c - YYYY-MM-DD 15:00:00 (XX minutes ago)
First commit - Christophe
git pull --rebase
ฉันไม่แน่ใจว่าฉันสามารถอธิบายได้ดีกว่าDerek Gourlay ... โดยทั่วไปใช้git pull --rebase
แทนgit pull
:) สิ่งที่ขาดหายไปในบทความนี้คือคุณสามารถเปิดใช้งานได้ตามค่าเริ่มต้น :
git config --global pull.rebase true
git rerere
อีกครั้งอย่างอธิบายที่นี่ แต่ถ้าคุณเปิดใช้งานคุณจะไม่ต้องแก้ไขข้อขัดแย้งซ้ำอีกหลายครั้ง
Pro Gitหนังสือมีคำอธิบายที่ดีจริงๆบนหน้า rebasing
โดยทั่วไปการรวมจะใช้เวลาสองคอมมิชชันและรวมเข้าด้วยกัน
การคืนเงินจะไปที่บรรพบุรุษร่วมกันของทั้งสองและนำการเปลี่ยนแปลงที่เพิ่มขึ้นมาใช้เพิ่มทีละส่วน สิ่งนี้ทำให้ประวัติ 'เชิงเส้น' สะอาดตาและเป็นเส้นตรงมากขึ้น
แต่เมื่อคุณรีบูตคุณละทิ้งหน้าที่ก่อนหน้านี้และสร้างใหม่ ดังนั้นคุณไม่ควรรีบูทพื้นที่เก็บข้อมูลสาธารณะ คนอื่นที่ทำงานในพื้นที่เก็บข้อมูลจะเกลียดคุณ
ด้วยเหตุนี้ฉันจึงรวมเข้าด้วยกันเป็นพิเศษ 99% ของเวลาที่สาขาของฉันไม่ได้แตกต่างกันมากดังนั้นหากมีความขัดแย้งจะมีเพียงแห่งเดียวหรือสองแห่ง
Git rebase ใช้ในการสร้างเส้นทางการแตกสาขาในตัวล้างประวัติและโครงสร้างที่เก็บข้อมูลเชิงเส้น
นอกจากนี้ยังใช้เพื่อให้สาขาที่คุณสร้างเป็นส่วนตัวเช่นเดียวกับการรีบูตและผลักดันการเปลี่ยนแปลงไปยังเซิร์ฟเวอร์หากคุณลบสาขาของคุณจะไม่มีหลักฐานของสาขาที่คุณได้ทำงาน ดังนั้นตอนนี้สาขาของคุณจึงเป็นข้อกังวลในท้องถิ่นของคุณ
หลังจากทำการ rebase เราก็กำจัดการกระทำพิเศษที่เราเคยดูว่าเราทำการผสานปกติหรือไม่
และใช่หนึ่งยังคงต้องรวมหลังจากการรีบูตที่ประสบความสำเร็จเป็นคำสั่ง rebase เพียงวางงานของคุณบนสาขาที่คุณกล่าวถึงในระหว่างการ rebase, พูดเจ้านายและทำให้ความมุ่งมั่นแรกของสาขาของคุณเป็นลูกหลานโดยตรงของสาขาหลัก . นี่หมายความว่าเราสามารถทำการผสานไปข้างหน้าอย่างรวดเร็วเพื่อนำการเปลี่ยนแปลงจากสาขานี้ไปยังสาขาหลัก
ตัวอย่างที่ใช้งานได้จริงบางอย่างเชื่อมโยงกับการพัฒนาขนาดใหญ่ที่Gerritใช้สำหรับการตรวจสอบและรวมการส่งมอบ:
ฉันรวมเมื่อยกระดับฟีเจอร์สาขาของฉันไปยังต้นแบบรีโมทใหม่ นี้จะช่วยให้การทำงานยกน้อยที่สุดและมันเป็นเรื่องง่ายที่จะปฏิบัติตามประวัติศาสตร์ของการพัฒนาคุณลักษณะในตัวอย่างgitk
git fetch
git checkout origin/my_feature
git merge origin/master
git commit
git push origin HEAD:refs/for/my_feature
ฉันรวมเมื่อฉันเตรียมส่งมอบ
git fetch
git checkout origin/master
git merge --squash origin/my_feature
git commit
git push origin HEAD:refs/for/master
ฉันรีบูตเมื่อการส่งมอบของฉันล้มเหลวในการรวมด้วยเหตุผลใดก็ตามและฉันจำเป็นต้องอัปเดตไปยังต้นแบบระยะไกลที่สดใหม่
git fetch
git fetch <gerrit link>
git checkout FETCH_HEAD
git rebase origin/master
git push origin HEAD:refs/for/master
มีการอธิบายหลายครั้งว่า rebase และการผสานคืออะไร แต่เมื่อใดคุณควรใช้อะไร
เมื่อใดที่คุณควรใช้ rebase
ในฐานะที่เป็น Git rebase การเปลี่ยนแปลงประวัติศาสตร์ ดังนั้นคุณไม่ควรใช้มันเมื่อมีคนอื่นทำงานในสาขาเดียวกัน / ถ้าคุณผลักมัน แต่ถ้าคุณมีสาขาในท้องที่คุณสามารถทำมาสเตอร์รีบูทการรวมก่อนที่จะรวมสาขาของคุณกลับไปเป็นมาสเตอร์เพื่อเก็บประวัติที่สะอาดกว่า การทำเช่นนี้หลังจากผสานเข้ากับสาขาหลักจะไม่ปรากฏให้เห็นว่าคุณใช้สาขาในสาขาหลัก - ประวัติคือ "สะอาด" เนื่องจากคุณไม่มีการผสานอัตโนมัติที่สร้างขึ้นโดยอัตโนมัติ แต่ยังมี ประวัติเต็มรูปแบบในสาขาหลักของคุณโดยไม่ต้องมี "การผสาน .. "
ตรวจสอบให้แน่ใจว่าคุณใช้git merge feature-branch --ff-only
เพื่อให้แน่ใจว่าไม่มีข้อขัดแย้งในการสร้างการคอมมิชชันเดียวเมื่อคุณรวมคุณสมบัติของคุณกลับไปยังหลักสิ่งนี้น่าสนใจหากคุณกำลังใช้สาขาฟีเจอร์สำหรับทุกงานที่คุณทำเมื่อคุณได้รับประวัติของฟีเจอร์สาขา แต่ไม่ใช่ "ผสานแล้ว"
สถานการณ์ที่สองจะเป็นถ้าคุณแยกจากสาขาและต้องการทราบว่ามีการเปลี่ยนแปลงอะไรในสาขาหลัก Rebase จะให้ข้อมูลกับคุณเนื่องจากมันรวมการกระทำทุกอย่าง
คุณควรใช้การผสานเมื่อใด
เมื่อคุณไม่ต้องการหรือต้องการที่จะมีประวัติของสาขาฟีเจอร์ในสาขาหลักของคุณหรือถ้าคนอื่นกำลังทำงานในสาขาเดียวกัน / คุณได้ผลักมัน หากคุณยังต้องการมีประวัติเพียงผสานต้นแบบเข้ากับสาขาคุณลักษณะก่อนที่จะรวมสาขาคุณลักษณะเข้ากับต้นแบบ สิ่งนี้จะส่งผลให้มีการผสานไปข้างหน้าอย่างรวดเร็วซึ่งคุณมีประวัติสาขาฟีเจอร์ในต้นแบบของคุณ (รวมถึงการรวมการคอมมิชชันที่อยู่ในสาขาฟีเจอร์ของคุณเพราะคุณผสานต้นแบบเข้าด้วย)
เมื่อไหร่ที่ผมใช้git rebase
? แทบไม่เคยเพราะมันเขียนประวัติศาสตร์ git merge
เป็นตัวเลือกที่ดีกว่าเกือบทุกครั้งเพราะมันเคารพสิ่งที่เกิดขึ้นจริงในโครงการของคุณ