รวมสองคอมมิตแรกของที่เก็บ Git หรือไม่?


197

สมมติว่าคุณมีประวัติที่มีทั้งสามยอมรับA, BและC :

A-B-C

ฉันต้องการรวมทั้งสองกระทำAและBกับหนึ่งกระทำAB :

AB-C

ฉันเหนื่อย

git rebase -i A

ซึ่งเปิดตัวแก้ไขของฉันด้วยเนื้อหาต่อไปนี้:

pick e97a17b B
pick asd314f C

ฉันเปลี่ยนสิ่งนี้เป็น

squash e97a17b B
pick asd314f C

จากนั้น Git 1.6.0.4 พูดว่า:

Cannot 'squash' without a previous commit

มีวิธีหรือเป็นไปไม่ได้?



คำตอบ:


169

ใช้git rebase -i --root เป็นของ Git รุ่น 1.7.12

ในไฟล์ rebase เชิงโต้ตอบเปลี่ยนบรรทัดที่สองของคอมมิตBเป็นสควอชและปล่อยให้บรรทัดอื่นที่เลือก :

pick f4202da A
squash bea708e B
pick a8c6abc C

นี้จะรวมทั้งสองกระทำและBให้เป็นหนึ่งกระทำAB

พบได้ในคำตอบนี้


126

คุณพยายาม:

git rebase -i A

มันเป็นไปได้ที่จะเริ่มต้นเช่นว่าถ้าคุณยังคงมีeditมากกว่าsquash:

edit e97a17b B
pick asd314f C

จากนั้นเรียกใช้

git reset --soft HEAD^
git commit --amend
git rebase --continue

เสร็จสิ้น


4
หากคุณกำลังทำสิ่งนี้เพื่อแก้ไข github gist อย่างเงียบ ๆ คุณจะต้องเพิ่ม -m "initial" ในการคอมมิท ;-)
Bruno Bronosky

1
git rebase --abortที่จะเริ่มต้นและทำมันได้วิธีการที่เหมาะสม (ไม่ฉับแรกได้กระทำการในการแก้ไข)
OMA

66

Aเป็นการกระทำเริ่มต้น แต่ตอนนี้คุณต้องการBที่จะกระทำการเริ่มต้น คอมไพล์เป็นคอมไพล์ต้นไม้ทั้งหมดไม่ต่างกันถึงแม้ว่าจะอธิบายและดูในแง่ของความแตกต่างที่แนะนำ

สูตรนี้ใช้ได้แม้ว่าจะมีหลายคอมมิชชันระหว่าง A และ B และ B และ C

# Go back to the last commit that we want
# to form the initial commit (detach HEAD)
git checkout <sha1_for_B>

# reset the branch pointer to the initial commit,
# but leaving the index and working tree intact.
git reset --soft <sha1_for_A>

# amend the initial tree using the tree from 'B'
git commit --amend

# temporarily tag this new initial commit
# (or you could remember the new commit sha1 manually)
git tag tmp

# go back to the original branch (assume master for this example)
git checkout master

# Replay all the commits after B onto the new initial commit
git rebase --onto tmp <sha1_for_B>

# remove the temporary tag
git tag -d tmp

1
สิ่งนี้ทริกเกอร์การลดการตอบโต้แบบโต้ตอบอย่างมากเมื่อฉันทำgit rebase --onto tmp <sha1_for_B>
Alex

พิจารณาว่าฉันมี repo ใหม่เอี่ยมที่มีเพียงสองคอมมิชชัน (ที่ฉันต้องการที่จะย้อนเป็นหนึ่ง) นี้ทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน ขอบคุณ @CB Bailey
RominRonin

10

ในกรณีที่มีการรีบูตแบบโต้ตอบคุณต้องทำก่อน A เพื่อรายการจะเป็น:

pick A
pick B
pick C

ที่จะกลายเป็น:

pick A
squash B
pick C

ถ้า A เป็นการกระทำเริ่มต้นคุณจะต้องมีการกระทำเริ่มต้นที่แตกต่างกันก่อนที่ A. Git จะคิดในความแตกต่างมันจะทำงานกับความแตกต่างระหว่าง (A และ B) และ (B และ C) ดังนั้นสควอชจึงไม่ทำงานในตัวอย่างของคุณ


9

ในกรณีที่คุณมีหลายร้อยหรือหลายพันกระทำโดยใช้คำตอบ kostmo ของของ

git rebase -i --root

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

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

git checkout --orphan orphan <second-commit-sha>
git commit -m "Enter a commit message for the new root commit"
git rebase --onto orphan <second-commit-sha> master

เอกสาร


1

ในคำถามที่เกี่ยวข้องฉันพยายามหาวิธีที่แตกต่างจากความต้องการในการต่อต้านการคอมมิชชันแรกซึ่งก็คือการทำให้เป็นครั้งที่สอง

หากคุณสนใจ: git: วิธีแทรกความมุ่งมั่นเป็นคนแรกเปลี่ยนคนอื่น ๆ ทั้งหมดได้อย่างไร


มันจะดีกว่าไหมถ้าคำตอบซ้ำที่นี่ด้วย? ฉันไม่แน่ใจ.

0

คำสั่ง Git สำหรับทีม: git rebase -i HEAD ~ [จำนวนคอมมิต]

ให้บอกว่าคุณมีคอมไพล์คอมมิทยืนยันประวัติ:


เลือก 5152061 feat: เพิ่มการสนับสนุนสำหรับการบันทึกภาพ (A)
เลือก 39c5a04 Fix: แก้ไขข้อบกพร่อง (B)
เลือกการแก้ไข 839c6b3: แก้ไขข้อขัดแย้ง (ค)

ตอนนี้คุณต้องการสควอช A และ B เป็น AB ดำเนินการด้านล่าง


เลือก 5152061 feat: เพิ่มการสนับสนุนสำหรับการบันทึกภาพ (A)
s 39c5a04 Fix: แก้ไขข้อบกพร่อง (B)
เลือกการแก้ไข 839c6b3: แก้ไขข้อขัดแย้ง (ค)

หมายเหตุ: สำหรับการส่งคำสั่งเราสามารถใช้สควอชหรือเอส ผลลัพธ์ที่ได้คือ:
เลือก 5152061 feat: เพิ่มการสนับสนุนสำหรับการบันทึกภาพ (AB)
เลือกการแก้ไข 839c6b3: แก้ไขข้อขัดแย้ง (ค)


-1

คุณต้องใช้เวทย์มนตร์บรรทัดคำสั่งเล็กน้อย

git checkout -b a A
git checkout B <files>
git commit --amend
git checkout master
git rebase a

ที่ควรปล่อยให้คุณมีสาขาที่มี AB และ C เป็นมั่นเหมาะ


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