ฉันจะ“ ยกเลิกการคืนสภาพ” Git ที่คืนกลับมาได้อย่างไร


485

เมื่อมีการเปลี่ยนแปลงที่กระทำโดยใช้commitแล้วเปลี่ยนกลับมาใช้revertวิธีที่ดีที่สุดในการยกเลิกการเปลี่ยนกลับเป็นอย่างไร

เป็นการดีที่ควรทำสิ่งนี้ด้วยความมุ่งมั่นใหม่เพื่อไม่ให้เขียนประวัติศาสตร์อีกครั้ง


4
มีความเป็นไปได้ที่ซ้ำกันของฉันจะแก้ไข git ที่คืนกลับมาได้อย่างไร
phuclv

@phuclv ความคิดเห็นสำหรับเป็นไปได้ซ้ำมีจุดที่นี่ จะต้องมีการทำเครื่องหมายว่าเป็นต้นฉบับและต้องมีการทำเครื่องหมายกำกับไว้
John Demetriou

@JohnDemetriou ไม่มีคำถามที่มีชุดคำตอบที่ดีกว่านี้ควรเปิดไว้ เวลาไม่เกี่ยวข้องที่นี่คำถามที่ควรจัดการซ้ำซ้อนอย่างไร
phuclv

ฉันไม่ได้พูดเกี่ยวกับเวลา ฉันเพิ่งจะแสดงความคิดเห็นในหนึ่งในสองเกี่ยวกับปัญหา
John Demetriou

คำตอบ:


385

หากคุณยังไม่ได้ผลักดันให้มีการเปลี่ยนแปลง git reset --hard HEAD^

มิฉะนั้นการคืนค่าการแปลงกลับจะสมบูรณ์แบบ

อีกวิธีหนึ่งคือการแล้วgit checkout HEAD^^ -- .git add -A && git commit


8
โปรดทราบว่าหากคุณต้องการยกเลิกการเปลี่ยนกลับโดยไม่ต้องใช้การเปลี่ยนแปลงดั้งเดิมกับสาขาหลักทันทีคุณสามารถ (1) กู้คืนสาขาเดิมหากถูกลบ (2) คลิก "เปลี่ยนกลับ" ในสาขาเปลี่ยนกลับตามที่ Adam ระบุไว้แล้ว ( 3) คลิก "แก้ไข" ในส่วนหัวของ PR ผลลัพธ์และเปลี่ยนสาขาเป้าหมายเป็นสาขาเดิมแทนต้นแบบ ตอนนี้สาขาเดิมของคุณสามารถรวมใหม่เพื่อให้มีผลกับการเปลี่ยนแปลงที่ย้อนกลับก่อนหน้านี้
pauljm

1
โปรดทราบว่านี่จะเป็นการลบการเปลี่ยนแปลงทั้งหมดในแผนผังการทำงานและดัชนี ใช้ git stash เพื่อบันทึกการเปลี่ยนแปลงใด ๆ ที่คุณไม่ต้องการเสีย
zpon

3
ข้อดีของวิธีการชำระเงิน && จะต้องทำอย่างไร ดูเหมือนว่าในกรณีทั่วไปgit cherry-pickหรืออีกวิธีหนึ่งgit revertเป็นวิธีที่ตรงไปตรงมาที่สุดในการเปลี่ยนคืน
Robert Jack Will

5
ฉันคิดว่ามันจะเป็นประโยชน์ในการแสดงวิธีการ: Otherwise, reverting the revert is perfectly fine.แล้วก็อธิบายสิ่งที่git checkout HEAD^^ -- .กำลังทำอยู่ด้วย
ทอดด์

3
ท่านดีอย่าใช้git add -A... เว้นแต่คุณจะต้องการเพิ่มทุกไฟล์ลงในการควบคุมเวอร์ชันซึ่งน่าจะไม่ใช่สิ่งที่คุณต้องการ
Kaitain

473

git cherry-pick <original commit sha>
จะทำสำเนาของการส่งต้นฉบับโดยการใช้การส่งมอบซ้ำ

การคืนค่าการเปลี่ยนกลับจะทำสิ่งเดียวกันโดยมีข้อความส่งเมสสิเยอร์:
git revert <commit sha of the revert>

วิธีใดวิธีหนึ่งเหล่านี้จะช่วยให้คุณgit pushไม่ต้องเขียนทับประวัติเพราะมันจะสร้างความมุ่งมั่นใหม่หลังจากเปลี่ยนกลับ
เมื่อพิมพ์คำสั่ง sha คุณจะต้องใช้อักขระ 5 หรือ 6 ตัวแรกเท่านั้น:
git cherry-pick 6bfabc


60
นี่เป็นทางออกที่ดีที่สุดและสมบูรณ์แบบสำหรับคำถาม OPs ดีกว่าคำตอบที่ได้รับการยอมรับโดยมีสมมติฐานเกี่ยวกับการเปลี่ยนกลับการกระทำที่อยู่ที่ HEAD ของแผนผังการส่งข้อมูล op ยังขอเฉพาะวิธีการแก้ปัญหาที่ไม่ได้เขียนประวัติดังนั้นการแก้ปัญหาอย่างหนักในคำตอบที่ยอมรับนั้นผิด
Timo

6
@Timo เพื่อชี้แจงคำตอบที่ได้รับการยอมรับมีวิธีแก้ไขที่ฉันใช้ ("การเปลี่ยนกลับ") และถูกโพสต์ภายในไม่กี่ชั่วโมงสำหรับคำถามของฉัน - ชัดเจน3 ปีกว่าคำตอบนี้ ดังนั้นเครื่องหมายถูก
JimmidyJoo

6
@JimmidyJoo ฉันรู้ว่าฉันเป็น 3 ปีปลายฉันเพียงแค่คนอยากมาที่นี่จากการค้นหาของ Google เพื่อดูคำตอบที่ดี
สเตฟาน

2
@Stephan Yep แต่อีกครั้งเพื่อชี้แจง - มันเป็นคำตอบที่ดีกว่าไม่ใช่คนที่ฉันใช้ในการแก้ปัญหาของฉัน ฉันแค่วิจารณ์ว่าทำไมเครื่องหมายถูกอยู่ตรงไหน คำถามทั้งหมด: อนุสัญญา SO กำหนดว่าฉันควร "รักษา" คำถามที่ผ่านมาของฉันและกำหนดเครื่องหมายถูกใหม่เมื่อมีคำตอบใหม่หรือไม่?
JimmidyJoo

3
@JimmidyJoo ฉันไม่มีความคิดเกี่ยวกับการประชุม SO แต่ในฐานะผู้ค้นหา google ฉันชอบดูคำตอบที่ดีกว่านี้ และขอขอบคุณทุกคนที่พยายามรักษาคำถามที่ผ่านมาไว้
Paiman Roointan

28

การย้อนกลับกระทำเหมือนกับการคอมมิทอื่น ๆ ในคอมไพล์ ความหมายคุณสามารถเปลี่ยนกลับได้เช่นเดียวกับใน:

git revert 648d7d808bc1bca6dbf72d93bf3da7c65a9bd746

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

ในทีมของเราเรามีกฎที่จะใช้การย้อนกลับใน Revert การกระทำที่มุ่งมั่นในสาขาหลักเพื่อรักษาความสะอาดของประวัติเป็นหลัก

      7963f4b2a9d   Revert "Revert "OD-9033 parallel reporting configuration"
      "This reverts commit a0e5e86d3b66cf206ae98a9c989f649eeba7965f.
                    ...
     a0e5e86d3b6    Revert "OD-9055 paralel reporting configuration"
     This reverts commit 648d7d808bc1bca6dbf72d93bf3da7c65a9bd746.
                ...
     Merge pull request parallel_reporting_dbs to master* commit 
    '648d7d808bc1bca6dbf72d93bf3da7c65a9bd746'

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

เห็นได้ชัดว่าหากกระทำความผิดย้อนกลับและย้อนกลับมากกว่าหนึ่งครั้งที่ค่อนข้างยุ่ง


14

การคืนค่าการเปลี่ยนกลับจะทำเคล็ดลับ

ตัวอย่างเช่น,

หากการabcdefกระทำของคุณเป็นและghijklการกระทำที่คุณมีเมื่อคุณย้อนกลับการกระทำabcdefนั้นให้เรียกใช้:

git revert ghijkl

สิ่งนี้จะเปลี่ยนกลับ


4

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

ตอนนี้ประวัติการกระทำของฉันดูแปลก ๆ

ประวัติแปลกประหลาด

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


4
คุณอาจสนใจคำตอบสำหรับคำถามอื่น ๆ ของฉัน: stackoverflow.com/questions/10415565/…
JimmidyJoo

2
คุณสามารถหลีกเลี่ยงการส่งข้อมูลอัตโนมัติและเลือกส่งข้อความโดยใช้การตั้งค่าสถานะ - ไม่ต้องส่งข้อมูลเมื่อทำการย้อนกลับแล้วส่งข้อความที่เกี่ยวข้อง
David Barda

นอกจากนี้คุณสามารถระบุรหัสยืนยันหลายรายการเมื่อใช้การย้อนกลับ git (พวกเขาต้องอยู่ในลำดับที่ถูกต้องที่ฉันคิด)
Aalex Gabi

ฉันสามารถทำสิ่งนั้นจากเดสก์ท็อป Github ได้หรือไม่?
Guillaume F.

4

นี่เป็นวิธีที่ฉันทำ:
ถ้าสาขาmy_branchnameรวมอยู่ในการผสานที่เปลี่ยนกลับ และฉันต้องการยกเลิกmy_branchname:

ครั้งแรกที่ผมทำจากgit checkout -b my_new_branchname จากนั้นฉันก็ทำที่ที่แฮชการกระทำถูกต้องก่อนที่จะคอมมิชชันแรก(ดู) จากนั้นฉันจะสร้างคอมมิทใหม่ จากนั้นฉันก็ดันสาขาใหม่ขึ้นมา จากนั้นฉันก็ดึงคำขอสำหรับสาขาใหม่my_branchname
git reset --soft $COMMIT_HASH$COMMIT_HASHmy_branchnamegit log
git commit -m "Add back reverted changes"
git push origin new_branchname


วิธีที่จะไปเมื่อมี "เชอร์รี่เลือก" มากเกินไปที่จะทำ ฉันไม่เข้าใจว่าทำไมคำตอบนี้มี upvotes น้อยมาก
Fundhor

2

หรือคุณสามารถgit checkout -b <new-branch>และgit cherry-pick <commit>ก่อนที่จะและgit rebaseจะลดลงrevertกระทำ ส่งคำขอการดึงเหมือนก่อน


1

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

รับสถานการณ์เริ่มต้นดังต่อไปนี้

 P---o---o---M---x---x---W---x
  \         /
   A---B---C----------------D---E   <-- fixed-up topic branch

(W คือการย้อนกลับครั้งแรกของคุณในการผสาน M; D และ E เป็นการแก้ไขสาขาย่อยที่เริ่มต้นของคุณ / กระทำ)

ตอนนี้คุณสามารถเล่นซ้ำกระทำ A ถึง E เพื่อไม่ให้พวกเขา "เป็น" เพื่อผสานรวมกลับ:

$ git checkout E
$ git rebase --no-ff P

สำเนาใหม่ของสาขาของคุณสามารถรวมกันได้masterอีกครั้ง:

   A'---B'---C'------------D'---E'  <-- recreated topic branch
  /
 P---o---o---M---x---x---W---x
  \         /
   A---B---C----------------D---E

ความคิดที่ดีและขอบคุณสำหรับลิงค์ doc โดยปกติเราจะทำการ rebase กับมาสเตอร์ก่อนที่จะรวมกลับเข้ามา แต่ดูเหมือนว่า git จะยอมรับว่า A ', B', C 'นั้นเหมือนกับก่อนหน้านี้และตอนนี้ฉันมี D, E หลัง W ( pastebin ) ข้อเสนอแนะเกี่ยวกับวิธีแก้ปัญหานี้?
Kristoffer Bakkejord

0

หากต้องการเรียกคืนการเปลี่ยนแปลงที่ไม่มีการจัดฉากและเป็นระยะซึ่งย้อนกลับหลังจากคอมมิชชัน:

git reset HEAD@{1}

ในการกู้คืนการลบที่ไม่ได้รับการจัดการทั้งหมด:

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