เลิกทำการคอมมิทเฉพาะใน Git ที่ถูกผลักไปที่ repos ระยะไกล


788

เป็นวิธีที่ง่ายที่สุดในการยกเลิกการกระทำที่เฉพาะเจาะจงคือ:

  • ไม่อยู่ในหัวหรือหัวหน้า
  • ได้ถูกผลักไปยังระยะไกล

เพราะถ้ามันไม่ได้กระทำล่าสุด

git reset HEAD

ไม่ทำงาน และเนื่องจากมันถูกผลักไปที่รีโมต

git rebase -i

และ

git rebase --onto

จะทำให้เกิดปัญหาในรีโมท

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

กล่าวอีกนัยหนึ่งสิ่งที่เทียบเท่าGitของคำสั่ง svn ต่อไปนี้:

svn merge -r 303:295 http://svn.example.com/repos/calc/trunk

ซึ่งจะลบการเปลี่ยนแปลงทั้งหมดจาก 295 ถึง 302 โดยย้อนกลับการรวมการเปลี่ยนแปลงทั้งหมดในการแก้ไขเหล่านั้นเป็นการกระทำใหม่

svn merge -c -302 ^/trunk

ซึ่งยกเลิกการกระทำ 302 แน่นอนโดยการเพิ่มการกระทำอื่นที่ย้อนกลับผสานการเปลี่ยนแปลงจากการกระทำนั้น ๆ

ฉันคิดว่ามันควรจะใช้งานได้ง่ายใน Git และกรณีการใช้งานที่ค่อนข้างธรรมดา ปรมาณูมีจุดมุ่งหมายอะไรอีก?

เรามีการจัดเตรียมstashingและทั้งหมดเพื่อให้แน่ใจว่าการกระทำนั้นสมบูรณ์แบบในระดับอะตอมคุณไม่ควรเลิกทำการคอมมิทเหล่านั้นอย่างน้อยหนึ่งอย่างได้อย่างง่ายดายหรือไม่?

คำตอบ:


1210

ระบุแฮชของการคอมมิชชันใช้git logแล้วใช้git revert <commit>เพื่อสร้างคอมมิทใหม่ที่ลบการเปลี่ยนแปลงเหล่านี้ ในทางหนึ่งgit revertคือการสนทนาgit cherry-pick- หลังนำ patch มาใช้กับสาขาที่ขาดหายไปอดีตจะลบมันออกจากสาขาที่มีอยู่


237
และใช้สวิตช์ -n หากคุณต้องการให้โค้ดกลับมา แต่จะไม่ทำการคอมมิทโดยอัตโนมัติอีกครั้ง
jaygooby

17
ตัวเลือก "m" ทำหน้าที่อะไร? ฉันพยายาม git ย้อนกลับ 8213f7d แต่ได้สิ่งนี้แทน: ข้อผิดพลาด: Commit 8213f7dad1ed546b434a0d8a64cb783b530a5a30 เป็นการผสาน แต่ไม่มีตัวเลือก -m ร้ายแรง: การย้อนกลับล้มเหลว
Malcolm

10
ในการคืนค่าการผสาน: git revert -m 1 <hash>
brunozrk

31
คำเตือนสำหรับผู้ที่ต้องการย้อนกลับการรวม: git revert จะยกเลิกการเปลี่ยนแปลงข้อมูลทั้งหมด (เช่นการเปลี่ยนแปลงไฟล์จะถูกเปลี่ยนกลับ) แต่การรวมยังคงอยู่ในประวัติ ด้วยเหตุนี้หากคุณพยายามผสานสาขาเดิมนั้นอีกครั้งในภายหลังจึงไม่รวมข้อผูกมัดใด ๆ จากสาขาที่ผสานก่อนที่จะรวมการคืนค่า นี่อาจไม่ใช่สิ่งที่คุณต้องการ ในการผสานสาขาอย่างเต็มที่อีกครั้งคุณจะต้องยกเลิกการยืนยันก่อนที่คุณจะคืนค่าการผสานเดิม เรียนรู้เพิ่มเติมที่นี่: kernel.mirrors.pair.com/pub/software/scm/git/docs/howto/ ......
etreworgy

3
การเชื่อมโยงในความคิดเห็นโดย @etreworgy เป็น 404 ฉันสงสัยว่านี้เป็นรุ่นล่าสุดของการเชื่อมโยง: kernel.org/pub/software/scm/git/docs/howto/...
ทิมสมิ ธ

368

ฉันไม่ชอบการกระทำอัตโนมัติที่git revertทำดังนั้นสิ่งนี้อาจเป็นประโยชน์สำหรับบางคน

หากคุณต้องการไฟล์ที่ถูกแก้ไขไม่ใช่การส่งอัตโนมัติคุณสามารถใช้--no-commit

% git revert --no-commit <commit hash>

ซึ่งเหมือนกันกับ -n

% git revert -n <commit hash>

9
คุณสามารถทำได้git reset HEAD~1 --softหากคุณเปลี่ยนกลับโดยไม่ต้อง-n
Daniel

1
แต่git reset HEAD~nจะไม่แก้ปัญหาการเลิกกระทำใด ๆ ที่ไม่สามารถเข้าถึงได้จากหัวอย่างต่อเนื่อง แบบสอบถามคือการย้อนกลับการกระทำใด ๆ
sangeethkumarp

ฉันใช้วิธีนี้ แต่โดนความขัดแย้งในช่วงกลางของการย้อนกลับ หลังจากแก้ไขข้อขัดแย้งฉันก็ทำgit revert --continueตามที่ฉันสั่ง มันใช้งานได้ แต่ให้ผลลัพธ์ที่น่าเศร้า git revert --no-commit --continueบางทีผมต้องทำ
mareoraft

1
@sangeethkumarp ความคิดเห็นโดยแดเนียลเป็นขั้นตอนเพิ่มเติมที่คุณสามารถใช้เวลาหลังจากที่git revertถ้าคุณลืม-n; เพราะ ณ จุดนั้นการคอมมิทครั้งล่าสุดคือการพลิกกลับดังนั้นซอฟต์รีเซ็ตจะยกเลิกการคอมมิท แต่ไม่ใช่การเปลี่ยนแปลงรหัสที่เกี่ยวข้องของการเปลี่ยนกลับ
Oliver

@Daniel ให้บริการโซลูชั่นโดยแสดงความคิดเห็นทำงานให้ฉันขอบคุณมาก '' git reset HEAD ~ 1 - soft ''
Md. Abu Sayed

41

เนื่องจากมีการส่งไปแล้วคุณไม่ควรจัดการประวัติโดยตรง git revertจะยกเลิกการเปลี่ยนแปลงบางอย่างจากการส่งข้อมูลโดยใช้การส่งข้อมูลใหม่เพื่อไม่ให้จัดการประวัติการส่งข้อมูล


1

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

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