ฉันจะใช้ git rebase โดยไม่ต้องกดบังคับได้อย่างไร


94

ในความพยายามที่จะบรรลุมรรคผลนิพพานฉันใช้เวลาทั้งวันในการเรียนรู้วิธีใช้ประโยชน์จาก rebase สำหรับสถานการณ์ที่ฉันรวมอยู่ในปัจจุบัน

เมื่อเรียกใช้สิ่งที่ฉันคิดว่าเป็นขั้นตอน git 101 (ซึ่งฉันสะกดไว้ด้านล่าง) ฉันต้องทำpush --forceเมื่อผลักการเปลี่ยนแปลงกลับไปที่จุดเริ่มต้น

ฉันไม่ใช่คนเดียว - ฉันรู้ว่าสิ่งนี้ถูกปกคลุมไปด้วยพื้น (ดู1 , 2 , 3 , 4 , 5 ) และฉันเข้าใจเหตุผลทางเทคนิคว่าทำไมต้องมีกองกำลัง ปัญหาของฉันคือ - มีรายการบล็อกจำนวนมาก (หลายรายการ) ที่ร้องเพลงสรรเสริญ rebase และการเปลี่ยนแปลงชีวิตของพวกเขา (ดู1 , 2 , 3 , 4เพื่อแสดงรายการบางส่วน) แต่ไม่มีรายการใดที่กล่าวถึงซึ่งpush --forceเป็นส่วนหนึ่งของ กระแสของพวกเขา อย่างไรก็ตามเกือบทุกคำตอบสำหรับคำถาม stackoverflow ที่มีอยู่จะบอกว่า "ใช่ถ้าคุณจะปรับฐานใหม่ก็ต้องใช้push --force"

ได้รับหมายเลขและศาสนาประชาสัมพันธ์ rebase ที่ฉันต้องเชื่อว่าการใช้ 'ดัน --force' ไม่ได้เป็นส่วนหนึ่งโดยธรรมชาติของการไหล rebase และว่าถ้ามีใครมักจะมีการบังคับให้ผลักดันของพวกเขาที่พวกเขากำลังทำอะไรผิดพลาด

push --forceเป็นสิ่งที่ไม่ดี

นี่คือขั้นตอนของฉัน ฉันจะบรรลุผลลัพธ์เดียวกันได้อย่างไรโดยไม่ต้องใช้แรง?

ตัวอย่างง่ายๆ

สองสาขา:

  • v1.0 - สาขารีลีสมีเฉพาะแพตช์
  • หลัก - ทุกอย่างสำหรับรุ่นหลักถัดไป

ฉันมีแพตช์คอมมิชชันสองสามคอมมิตและคอมมิตสำหรับรีลีสถัดไป

premerge

ฉันต้องการรวมแพตช์ไว้ในต้นแบบของฉันเพื่อไม่ให้สูญหายไปในรุ่นถัดไป ก่อนการตรัสรู้ฉันเพียงแค่:

git checkout master
git merge v1.0

แต่ตอนนี้ฉันกำลังพยายาม

git checkout master
git rebase v1.0

ตอนนี้ฉันอยู่ที่นี่:

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

เวลาสำหรับ:

git push

ไม่มีลูกเต๋า

คำตอบ:


43

Rebasing เป็นเครื่องมือที่ยอดเยี่ยม แต่จะได้ผลดีที่สุดเมื่อคุณใช้เพื่อสร้างการผสานไปข้างหน้าอย่างรวดเร็วสำหรับสาขาหัวข้อไปยังต้นแบบ ตัวอย่างเช่นคุณอาจปรับฐานสาขา add-new-widget เทียบกับ master:

git checkout add-new-widget
git rebase -i master

ก่อนที่จะดำเนินการรวมสาขาไปข้างหน้าอย่างรวดเร็วเป็นหลัก ตัวอย่างเช่น:

git checkout master
git merge --ff-only add-new-widget

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

นั่นไม่ใช่กรณีการใช้งานเพียงอย่างเดียวสำหรับ rebase หรือเวิร์กโฟลว์เพียงอย่างเดียว แต่เป็นการใช้งานที่สมเหตุสมผลกว่าที่ฉันเคยเห็น YMMV.


4
ขอบคุณ CG ฉันคิดว่า "ใช้เพื่อสร้างการผสานไปข้างหน้าอย่างรวดเร็ว" คือกุญแจสำคัญ มันใช้ไม่ได้กับกรณีของฉันข้างต้นที่ฉันมีสองสาขาอยู่ - สาขาการพัฒนาและสาขาการเผยแพร่ แต่ดูเหมือนว่าจะใช้ได้ดีกับสาขาหัวข้อชั่วคราวที่จำเป็นสำหรับช่วงเวลาที่ จำกัด เท่านั้นจากนั้นก็สามารถเป็นได้ จะถูกลบเมื่อรวมเข้าด้วยกัน ขอบคุณอีกครั้ง.
Roy Truelove

1
ฉันเข้าใจสิ่งนี้ แต่คำถามเดิมยังคงอยู่ ฉันคิดว่าคำตอบที่แท้จริงคือคำตอบที่ได้รับจาก@Fabien Quatravaux
IsmailS

5
คุณยังคงต้องบังคับให้ผลักดันสาขา 1.0 ไม่ใช่เหรอ? อย่างน้อยนั่นคือสิ่งที่มักเกิดขึ้นกับฉันตลอดเวลา วิธี Fabiens จะป้องกันไม่ให้เกิดขึ้น
joerx

23

@CodeGnome พูดถูก คุณไม่ควร rebase master ใน v1.0 branch แต่ v1.0 branch บน master ซึ่งจะสร้างความแตกต่างทั้งหมด

git checkout -b integrate_patches v1.0
git rebase master
git checkout master
git merge integrate_patches

สร้างสาขาใหม่ที่ชี้ไปที่ v1.0 ย้ายสาขาใหม่นั้นไปที่ด้านบนของมาสเตอร์แล้วรวมแพตช์ V1.0 เวอร์ชันใหม่เข้ากับสาขาหลัก คุณจะได้สิ่งที่ต้องการ:

o [master] [integrate_patches] Another patch on v1.0
o A patch on v1.0
o Another change for the next major release
o Working on the next major release
|  o [v1.0] Another path on v1.0
|  o A patch on v1.0
| /
o Time for the release

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

ฉันคิดว่าคุณพูดถูกgit push --force: คุณควรใช้เมื่อคุณทำผิดพลาดและผลักดันสิ่งที่คุณไม่ต้องการเท่านั้น


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

ขอบคุณ Fabien คำตอบที่ดี สำหรับพวกเราที่ต้องการรวมการเปลี่ยนแปลงเข้าด้วยกันmasterและไม่สนใจที่จะรวมสาขาคุณลักษณะเข้าด้วยกันสามารถทำได้ด้วย:git checkout my-branch; git rebase master; git checkout master; git merge my-branch
Siavas

17

คุณต้องบังคับผลักดันหากคุณปรับฐานใหม่และคุณได้เผยแพร่การเปลี่ยนแปลงของคุณแล้วใช่ไหม

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

นี่คือหัวใจหลักของเวิร์กโฟลว์ที่คุณใช้ rebase แต่อย่าบังคับให้พุชมาก: อย่าเผยแพร่สิ่งต่างๆจนกว่าจะพร้อมอย่าตั้งฐานใหม่หลังจากที่คุณพุช


ขอบคุณแดน คุณช่วยแจ้งให้เราทราบได้ไหมว่าข้างต้นควรบรรลุอย่างไร นี่ไม่ใช่สถานการณ์ที่ใช้ rebase หรือไม่?
Roy Truelove

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

1
ปัญหาคือคุณได้เผยแพร่สาขาแล้วดังนั้นคุณต้องบังคับให้พุชไปที่ที่เก็บ คุณต้องสละหนึ่งในสองสิ่งนี้: การเผยแพร่ในแบบที่คุณทำหรือการทำใหม่ ขออภัย.
Daniel Pittman

ดูเหมือนว่าการรีเบตใหม่จะใช้ไม่ได้กับสถานการณ์นี้ v1.0 ไม่ใช่สาขาหัวข้อ แต่เป็นสาขาเผยแพร่ดังนั้นจึงไม่มีวันตายและต้องเผยแพร่
Roy Truelove

5

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


2
ฉันมีเวิร์กโฟลว์เดียวกันนี้ (ทำงานจากคอมพิวเตอร์ / สถานที่หลายเครื่อง) สมมติว่าคุณกำลังทำงานในหัวข้อที่เรียกว่า 'mytopic' ตราบเท่าที่คุณตั้งฐานข้อมูลสาขาการทิ้งในพื้นที่ (ซึ่งเป็นเพียงสาขาหนึ่งของ mytopic) ไปยัง "master" จากนั้นรวมกลับเข้าไปใน mytopic คุณก็ไม่ต้องออกแรงผลัก OP มีสถานการณ์ที่แตกต่างกันเล็กน้อยดังนั้นในกรณีเช่นนี้อาจจำเป็นต้องใช้แรงผลัก อย่างไรก็ตามฉันคิดว่า OP กำลังเปลี่ยนวิธีการที่ผิด - ถ้าเขาทำตามที่ฉันอธิบายไว้ก็ไม่จำเป็นต้องใช้แรงผลัก
bwv549

3

นี่คือสิ่งที่ฉันใช้ (สมมติว่าชื่อสาขาของคุณคือfoobar ):

git checkout master              # switch to master
git rebase   foobar              # rebase with branch
git merge -s ours origin/master  # do a basic merge -- but this should be empty
git push origin master           # aaand this should work

2
มาสเตอร์รีเบตดูแปลก ๆ
Emil Vikström

2
gitไม่ได้ไร้บุคลิก
redolent

1
git merge -s ours origin/<branch>คือสิ่งที่แก้ไขให้เรา
สูงสุด

0

tl; dr ผสานกับสาขาที่ใช้ร่วมกัน, rebase กับแต่ละสาขา --force-with-leaseเป็นทางเลือกที่ปลอดภัยกว่าในการบังคับและควรช่วยให้คุณบรรลุมรรคผลนิพพานดังกล่าวโดยปราศจากการทำลาย

หลักการทั่วไปที่ฉันเคยเห็นในการทำงานสำหรับเวิร์กโฟลว์ของทีมต่างๆคือใช้mergeสำหรับสาขาที่ใช้ร่วมกัน (เช่นต้นแบบหรือพัฒนา) และใช้rebaseเมื่อทำงานกับสาขาคุณลักษณะของคุณเอง นี่คือวงจรชีวิตทั่วไปของสาขาคุณลักษณะ

git checkout master
git checkout -b new-feature
git commit -am "commit new work"
git push -u origin new-feature
# have code reviewed, run CI, etc.,
# meanwhile master has new commits
git checkout master
git pull
git rebase -i master # -i for interactive rebase allows you to squash intermediate commits
git push --force-with-lease
git merge master

เวอร์ชันภาษาอังกฤษธรรมดาของสิ่งที่เราได้ทำที่นี่:

  1. สร้างสาขาใหม่จากต้นแบบ
  2. ทำงานในสาขาและส่งไปยังรีโมต
  3. ปลดออกจากอาจารย์
  4. ผลักงานไปที่ระยะไกลด้วย force-with-lease
  5. รวมเป็นมาสเตอร์ด้วยบันทึกคอมไพล์ที่สะอาดมากช่วยลดความยุ่งเหยิงจากการผสานหลายรายการจากสาขาที่แชร์ของเราเพื่อให้สาขาของเรา "ตามทัน" กับมาสเตอร์ล่าสุด (สาขาที่แชร์)

ขั้นตอนที่ 4 มีความสำคัญมากและเป็นหนึ่งในเหตุผลหลักที่ฉันเริ่มสนับสนุนการใช้ rebase force-with-leaseตรวจสอบรีโมทเพื่อดูว่ามีการเพิ่มคอมมิตใหม่หรือไม่ หากคุณgit pushได้รับการพิสูจน์แล้วว่าทำลายล้างมันจะไม่ผลักดัน!

ฉันหวังว่าสิ่งนี้จะช่วยให้ใครบางคนมีความมั่นใจมากขึ้นในการใช้ rebase

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