ฉันต้องการป๊อปอัปและทิ้งคอมมิต "กลาง" ในสาขาหลักของฉัน ฉันจะทำมันได้อย่างไร?


96

ตัวอย่างเช่นในสาขาหลักต่อไปนี้ฉันต้องทิ้งเฉพาะการกระทำ af5c7bf16e6f04321f966b4231371b21475bc4da ซึ่งเป็นครั้งที่สองเนื่องจาก rebase ก่อนหน้านี้:

commit 60b413512e616997c8b929012cf9ca56bf5c9113
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Tue Apr 12 23:50:15 2011 +0200

    add generic config/initializers/omniauth.example.rb

commit af5c7bf16e6f04321f966b4231371b21475bc4da
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Fri Apr 22 00:15:50 2011 +0200

    show github user info if logged

commit e6523efada4d75084e81971c4dc2aec621d45530
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Fri Apr 22 17:20:48 2011 +0200

    add multiple .container at blueprint layout

commit 414ceffc40ea4ac36ca68e6dd0a9ee97e73dee22
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Thu Apr 21 19:55:57 2011 +0200

    add %h1 Fantastic Logo + .right for 'Sign in with Github'

ฉันต้องมนต์

  • การกระทำครั้งแรก 60b413512e616997c8b929012cf9ca56bf5c9113
  • ที่สามกระทำ e6523efada4d75084e81971c4dc2aec621d45530 และ
  • คอมมิตสุดท้าย 414ceffc40ea4ac36ca68e6dd0a9ee97e73dee22

"ทิ้ง" เพียงวินาทีกระทำaf5c7bf16e6f04321f966b4231371b21475bc4da

ฉันจะทำเช่นนั้นได้อย่างไร? ขอบคุณล่วงหน้า Luca

คำตอบ:


103

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

การเปลี่ยนกลับเป็นวิธีแก้ไขที่ถูกต้องเมื่อมีการแชร์สาขากับ repos อื่น ๆ git revert af5c7bf16จะทำการคอมมิตใหม่ที่เพียงแค่ย้อนกลับการเปลี่ยนแปลงที่แนะนำ af5c7bf16 วิธีนี้จะไม่เขียนประวัติซ้ำคุณจะรักษาบันทึกที่ชัดเจนของความผิดพลาดและ repos อื่น ๆ จะยอมรับการผลักดัน

นี่เป็นวิธีที่ดีในการลบ: git rebase -i <commit>^ ซึ่งจะนำคุณไปสู่การกระทำก่อนหน้าที่คุณต้องการลบ ตัวแก้ไขแบบโต้ตอบจะแสดงรายการการกระทำทั้งหมดที่กลับไปยังจุดนั้น คุณสามารถเลือกสควอช ฯลฯ ในกรณีนี้ให้ลบบรรทัดสำหรับการคอมมิตที่คุณต้องการลบและบันทึกไฟล์ Rebase จะทำงานให้เสร็จ


2
ในกรณีที่ฉันจะเลือก Rebase อะไรคือสิ่งที่ถูกต้องในการ rebase? ฉันต้องลดลงแค่วินาที ...
Luca G. Soave

@ BBJ3 ดูคำตอบของ mipadi
Prajwal Dhatwalia

34

หาก rebase เป็นตัวเลือกคุณสามารถ rebase และปล่อยมัน:

$ git rebase -i 414ceffc^

หาก rebase ไม่ใช่ตัวเลือกคุณสามารถเปลี่ยนกลับได้:

$ git revert af5c7bf16

ถ้าฉันได้รับ "git rebase 414ceffc" ซึ่งเป็นค่าคอมมิทที่เก่ากว่าอย่า 'ฉันจะปล่อย e6523 ตัวที่สามและ 60b41 ตัวแรกหรือไม่
Luca G. Soave

3
@Luca G. Soave: คุณจะ "เสีย" การกระทำหากคุณบอกgit rebaseให้วางโดยเฉพาะ (โดยการเรียกใช้rebaseในโหมดโต้ตอบและลบรายการออก)
mipadi

ขอบคุณ mipadi ฉันให้คะแนน JCotton เป็นหลักสำหรับคำอธิบายที่ครอบคลุมแม้ว่าคุณสองคนจะพูดในสิ่งเดียวกัน ... ขอบคุณอีกครั้ง
Luca G. Soave

30

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

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

นี่คือข้อมูลเกี่ยวกับ Cherry Picking: การเลือก เชอร์รี่ด้วยคอมไพล์หมายถึงอะไร?

นี่คือบางส่วนเกี่ยวกับการใช้ Tortoise Git (อย่างที่ฉันเพิ่งทำ) มันง่ายกว่าที่จะใช้ยูทิลิตี้ gui สำหรับการทำงานประเภทนี้! เลือกเชอร์รี่โดยใช้ TortoiseGit


6
นี่น่าจะเป็นคำตอบอันดับต้น ๆ !
MadOgre

วิธีที่ดีในการใช้การเลือกเชอร์รี่วิธีนี้ดียิ่งขึ้นเมื่อคุณต้องการ "ข้าม" มากกว่าหนึ่งคอมมิต
Johnny Willer

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