การรีบูตการคอมไพล์ Git


183

ใช้กรณีต่อไปนี้:

ฉันมีงานในสาขาหัวข้อและตอนนี้ฉันพร้อมที่จะรวมกลับไปเป็นหลัก:

* eb3b733 3     [master] [origin/master]
| * b62cae6 2   [topic]
|/  
* 38abeae 1

ฉันดำเนินการผสานจากต้นแบบแก้ไขข้อขัดแย้งและตอนนี้ฉันมี:

*   8101fe3 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
* | eb3b733 3                     [origin/master]
|/  
* 38abeae 1

ตอนนี้การผสานใช้เวลาพอสมควรดังนั้นฉันจึงทำการดึงข้อมูลอีกครั้งและสังเกตว่าสาขาต้นแบบระยะไกลมีการเปลี่ยนแปลงใหม่:

*   8101fe3 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
| | * e7affba 4                   [origin/master]
| |/  
|/|   
* | eb3b733 3
|/  
* 38abeae 1

หากฉันลอง 'git rebase origin / master' จากต้นแบบฉันถูกบังคับให้แก้ไขข้อขัดแย้งทั้งหมดอีกครั้งและฉันก็ต้องทำตามคำสั่งผสาน:

* d4de423 2       [master]
* e7affba 4       [origin/master]
* eb3b733 3
| * b62cae6 2     [topic]
|/  
* 38abeae 1

มีวิธีที่สะอาดในการลดการรวมเพื่อให้ฉันจบด้วยประวัติเหมือนที่ฉันแสดงด้านล่างหรือไม่

*   51984c7 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
* | e7affba 4                     [origin/master]
* | eb3b733 3
|/  
* 38abeae 1

74
TL: DR:git rebase --preserve-merges origin/master
Ilia K.

6
ด้วยความเคารพต่อการแก้ไขความขัดแย้งคุณอาจต้องการดูgit rerereอีกครั้ง
Parker Coates

git config --global pull.rebase preserve เพื่อรักษาความมุ่งมั่นที่ผสานไว้เสมอในระหว่างการ rebase
galath

4
คำเตือน: เริ่มต้นด้วย Git 2.18 (Q2 2018 5 ปีต่อมา) ในที่สุดจะแทนที่เดิมgit --rebase-merges git --preserve-mergesดูสิ่งที่ Git rebase --preserve-mergesทำ“” ทำ (และทำไม?)
VonC

1
--preserve-mergesเลิกใช้แล้ว ใช้git rebase --rebase-merges origin/master
Arjun Sreedharan

คำตอบ:


127

มีสองตัวเลือกที่นี่

หนึ่งคือการทำ rebase แบบโต้ตอบและแก้ไขการคอมมิชชันรวมการทำซ้ำการผสานด้วยตนเองและดำเนินการ rebase ต่อ

อีกวิธีหนึ่งคือการใช้--rebase-mergesตัวเลือกgit rebaseซึ่งอธิบายไว้ดังต่อไปนี้จากคู่มือ: "โดยค่าเริ่มต้น rebase เพียงแค่จะรวมการกระทำจากรายการสิ่งที่ต้องทำและวาง rebits กระทำในสาขาเชิงเส้นเดียวด้วย --rebase- การรวมการรีบูตจะพยายามรักษาโครงสร้างการแยกย่อยภายในคอมมิทที่จะทำการรีบูตโดยการสร้างคอมมิชชันใหม่การรวมความขัดแย้งที่แก้ไขแล้วหรือการแก้ไขด้วยตนเองในคอมมิทการรวมเหล่านี้จะต้องแก้ไข / นำไปใช้ใหม่ด้วยตนเอง "


16
ฉันลองใช้ตัวเลือก -p และแน่นอนว่าจะทิ้งประวัติการกระทำตามที่ฉันต้องการ แต่มันบังคับให้ฉันแก้ไขข้อขัดแย้งอีกครั้งแม้ในไฟล์ที่ไม่ได้แก้ไขใน Origin / master ในข้อเสนอแนะแรกของคุณคำสั่งลำดับใดที่แม่นยำ?
jipumarino

2
@ jipumarino: git rebase -i (บอกให้แก้ไขการคอมมิชชันคอมมิชชัน), เมื่อได้รับการคอมมิชชันคอมไพล์, รีเซท git - ฮาร์ด HEAD ^, คอมไพล์ git, แก้ไขความขัดแย้ง, คอมไพล์ rebase - คอมไพล์ คุณอาจต้องการดู ger rerere ซึ่งควรจะช่วยในเรื่องนี้ (แต่ฉันไม่เคยใช้ดังนั้นฉันจึงไม่สามารถให้คำแนะนำหรือความช่วยเหลือใด ๆ )
23909 siride

2
ขอบคุณ ฉันเปิดใช้งาน rerere และลองใช้ rebase -p และทำงานได้ตามที่ควรจะเป็น
jipumarino

3
นี่คือบล็อกโพสต์ที่ยอดเยี่ยมที่อธิบายถึงสถานการณ์ที่แน่นอนนี้: Rebasing Merge Commits ใน Git
kynan

1
ไม่ใช่วิธีการแก้ปัญหาเนื่องจากคุณยังคงต้องแก้ไขการรวมด้วยตนเองในครั้งแรก
Flimm

29

ตกลงนั่นเป็นคำถามเก่าและได้รับคำตอบ@sirideแล้ว แต่คำตอบนั้นไม่เพียงพอในกรณีของฉันเนื่องจาก--preserve-mergesบังคับให้คุณแก้ไขข้อขัดแย้งทั้งหมดในครั้งที่สอง วิธีการแก้ปัญหาของฉันขึ้นอยู่กับความคิดโดย@Tobi Bแต่มีคำสั่งทีละขั้นตอนที่แน่นอน

ดังนั้นเราจะเริ่มจากสถานะดังกล่าวตามตัวอย่างในคำถาม:

*   8101fe3 Merge branch 'topic'  [HEAD -> master]
|\  
| * b62cae6 2                     [topic]
| |
| | * f5a7ca8 5                   [origin/master]
| | * e7affba 4
| |/  
|/|   
* | eb3b733 3
|/  
* 38abeae 1

โปรดทราบว่าเรามีผู้เล่น 2 คนที่มุ่งหน้าไปก่อนดังนั้นการหยิบเชอร์รี่จะไม่ทำงาน

  1. ก่อนอื่นให้สร้างประวัติที่ถูกต้องที่เราต้องการ:

    git checkout -b correct-history # create new branch to save master for future
    git rebase --strategy=ours --preserve-merges origin/master
    

    เราใช้--preserve-mergesเพื่อบันทึกการรวมการกระทำของเราในประวัติศาสตร์ เราใช้--strategy=oursเพื่อเพิกเฉยต่อข้อขัดแย้งที่ผสานทั้งหมดเนื่องจากเราไม่สนใจว่าเนื้อหาใดจะอยู่ในการรวมที่กระทำนั้นเราต้องการเพียงแค่ประวัติที่ดี

    ประวัติจะเป็นเช่นนั้น (ไม่สนใจอาจารย์):

    *   51984c7 Merge branch 'topic'  [HEAD -> correct-history]
    |\  
    | * b62cae6 2                     [topic]
    * | f5a7ca8 5                     [origin/master]
    * | e7affba 4
    * | eb3b733 3
    |/  
    * 38abeae 1
    
  2. มารับดัชนีที่ถูกต้องกันก่อน

    git checkout master # return to our master branch
    git merge origin/master # merge origin/master on top of our master
    

    เราอาจได้รับความขัดแย้งในการรวมเพิ่มเติมที่นี่ แต่นั่นอาจเป็นเพียงความขัดแย้งจากไฟล์ที่เปลี่ยนไประหว่าง8101fe3และf5a7ca8แต่ไม่รวมถึงความขัดแย้งที่แก้ไขแล้วจากtopic

    ประวัติจะมีลักษณะเช่นนี้ (ละเว้นประวัติที่ถูกต้อง):

    *   94f1484 Merge branch 'origin/master'  [HEAD -> master]
    |\  
    * | f5a7ca8 5                   [origin/master]
    * | e7affba 4
    | *   8101fe3 Merge branch 'topic'
    | |\  
    | | * b62cae6 2                     [topic]
    |/ /
    * / eb3b733 3
    |/  
    * 38abeae 1
    
  3. ขั้นตอนสุดท้ายคือการรวมสาขาของเรากับประวัติและสาขาที่ถูกต้องกับดัชนีที่ถูกต้อง

    git reset --soft correct-history
    git commit --amend
    

    เราใช้reset --softเพื่อรีเซ็ตสาขาของเรา (และประวัติ) เพื่อแก้ไขประวัติ แต่ปล่อยให้ดัชนีและแผนผังการทำงานตามที่เป็นอยู่ จากนั้นเราใช้commit --amendในการเขียนรวมการกระทำของเราที่เคยมีดัชนีที่ไม่ถูกต้องกับดัชนีที่ดีของเราจากต้นแบบ

    ในท้ายที่สุดเราจะมีสถานะดังกล่าว (หมายเหตุอีกรหัสหนึ่งของการกระทำที่มีชื่อเสียง):

    *   13e6d03 Merge branch 'topic'  [HEAD -> master]
    |\  
    | * b62cae6 2                     [topic]
    * | f5a7ca8 5                     [origin/master]
    * | e7affba 4
    * | eb3b733 3
    |/  
    * 38abeae 1
    

มันยอดเยี่ยมมากและช่วยได้มาก! แต่ฉันไม่ได้รับเคล็ดลับด้วยความมุ่งมั่น - แก้ไข: คุณช่วยเพิ่มข้อมูลเพิ่มเติมได้ไหม? จะเกิดอะไรขึ้นหลังจากที่คุณเรียกใช้แล้ว - ฉันสังเกตเห็นว่า SHA of commit มีการเปลี่ยนแปลง - แต่ทำไม? หรือจะเกิดอะไรขึ้นถ้าคุณไม่ทำสิ่งนี้?
ZenJ

1
@ZenJ git commit --amendเพิ่มการเปลี่ยนแปลงในการส่งมอบครั้งล่าสุด (HEAD ในกรณีนี้การรวมการกระทำ) เนื่องจากเนื้อหาการคอมมิชชันเปลี่ยนแปลงแฮชจะถูกอัพเดต
Dries Staelens

1
สำหรับผู้ที่ไม่ได้เปิดใช้งาน 'rerere' ก่อนที่จะแก้ไขข้อขัดแย้งโซลูชันนี้ยอดเยี่ยมเพราะช่วยให้คุณไม่ต้องแก้ไขข้อขัดแย้งอีกครั้ง ขอบคุณ!
Shackleford

6

เนื่องจากฉันเพิ่งเสียวันพยายามคิดและพบวิธีแก้ปัญหาด้วยความช่วยเหลือของเพื่อนร่วมงานฉันคิดว่าฉันควรจะพูดสอด

เรามีฐานรหัสขนาดใหญ่และเราต้องจัดการกับ 2 สาขาอย่างมากที่ถูกแก้ไขในเวลาเดียวกัน มีสาขาหลักและสาขารองถ้าคุณซึ่ง

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

ฉันจึงต้อง "ลด" ของ "ผสาน" ของฉัน

นี่คือวิธีที่เราทำในที่สุด:

1) จดบันทึก SHA เช่น. c4a924d458ea0629c0d694f1b9e9576a3ecf506b

git log -1

2) สร้างประวัติที่เหมาะสม แต่สิ่งนี้จะทำให้การรวมพัง

git rebase -s ours --preserve-merges origin/master

3) จดบันทึก SHA เช่น.: 29dd8101d78

git log -1

4) ตั้งค่าใหม่เป็นที่ที่คุณเคยอยู่

git reset c4a924d458ea0629c0d694f1b9e9576a3ecf506b --hard

5) ตอนนี้รวมต้นแบบปัจจุบันในสาขาการทำงานของคุณ

git merge origin/master
git mergetool
git commit -m"correct files

6) ตอนนี้คุณมีไฟล์ที่ถูกต้องแล้ว แต่ประวัติที่ไม่ถูกต้องได้รับประวัติที่ถูกต้องด้านบนของการเปลี่ยนแปลงของคุณด้วย:

git reset 29dd8101d78 --soft

7) จากนั้น - แก้ไขผลลัพธ์ในการผสานเดิมของคุณ

git commit --amend

Voila!


1

ดูเหมือนว่าคุณต้องการทำคือลบการรวมครั้งแรกของคุณ คุณสามารถทำตามขั้นตอนต่อไปนี้:

git checkout master      # Let's make sure we are on master branch
git reset --hard master~ # Let's get back to master before the merge
git pull                 # or git merge remote/master
git merge topic

นั่นจะให้สิ่งที่คุณต้องการ


4
ด้วยการเปิดใช้งาน rerere ดูเหมือนว่าจะให้ผลลัพธ์เช่นเดียวกับโซลูชัน rebase -p ที่กำหนดโดย Siride
jipumarino

0
  • จากการรวมของคุณกระทำ
  • เชอร์รี่เลือกการเปลี่ยนแปลงใหม่ที่ควรจะง่าย
  • คัดลอกข้อมูลของคุณ
  • ทำซ้ำการผสานและแก้ไขข้อขัดแย้งโดยเพียงคัดลอกไฟล์จากสำเนาในเครื่องของคุณ)

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