วิธีใช้ Git Revert


110

วิธีการgit revertใช้งานอย่างไร

นี่อาจฟังดูเหมือนคำถามซ้ำกัน แต่เมื่อมีคนถามคำตอบมักจะใช้git resetตามการเปลี่ยนกลับเป็นการคอมมิตโดยแฮช SHA ใน Git?

จากนั้นเมื่อมีคนถามวิธีใช้git resetคนตอบว่าคุณควรใช้git revertตามGit - วิธีย้อนกลับ

ก่อนที่คุณจะรู้ว่ามีคน 8 คนที่แตกต่างกันปรากฏตัวขึ้นพร้อมกับวิธีที่เป็นเอกลักษณ์ของตนเองในการช่วยลาของ OP ซึ่งทั้งหมดนี้อยู่เหนือหัวของคุณ

เพื่อช่วยให้ลองและติดสั้นและเขียนคู่มือ Dummies git revertไป

สถานการณ์: คุณได้มุ่งมั่นที่จะเชี่ยวชาญสองครั้งและไม่ดี คุณผลักดันและคนอื่น ๆ ก็ได้รับการเปลี่ยนแปลงที่ไม่ดีของคุณ

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

นี่คือสิ่งที่การควบคุมแหล่งที่มาเป็นข้อมูลเกี่ยวกับ ฉันมั่นใจว่ามันง่าย

โอเคคุณจะใช้git revertแต่อย่างไร

แล้วหลังวิ่งgit revertต้องทำอะไรอีกไหม? คุณต้องยอมรับการเปลี่ยนแปลงที่ทำกลับไปหรือเปลี่ยนกลับเป็นการกระทำโดยตรงกับ repo หรืออะไร ??

แน่นอนว่าคุณจะต้องผลักดันอีกครั้งและอาจประกาศการส่งบอลให้กับทีม

คำตอบ:


124

git revert ทำให้คอมมิตใหม่

git revert เพียงแค่สร้างคอมมิตใหม่ที่ตรงข้ามกับคอมมิตที่มีอยู่

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

$ cd /tmp/example
$ git init
Initialized empty Git repository in /tmp/example/.git/
$ echo "Initial text" > README.md
$ git add README.md
$ git commit -m "initial commit"
[master (root-commit) 3f7522e] initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
$ echo "bad update" > README.md 
$ git commit -am "bad update"
[master a1b9870] bad update
 1 file changed, 1 insertion(+), 1 deletion(-)

ในตัวอย่างนี้ประวัติการกระทำมีสองคอมมิตและอันสุดท้ายคือความผิดพลาด ใช้ git revert:

$ git revert HEAD
[master 1db4eeb] Revert "bad update"
 1 file changed, 1 insertion(+), 1 deletion(-)

จะมีการคอมมิต 3 ครั้งในบันทึก:

$ git log --oneline
1db4eeb Revert "bad update"
a1b9870 bad update
3f7522e initial commit

ดังนั้นจึงมีประวัติที่สอดคล้องกันว่าเกิดอะไรขึ้น แต่ไฟล์ก็เหมือนกับว่าไม่มีการอัปเดตที่ไม่ดีเกิดขึ้น:

cat README.md 
Initial text

ไม่สำคัญว่าการคอมมิตที่จะเปลี่ยนกลับจะอยู่ที่ใดในประวัติศาสตร์ (ในตัวอย่างด้านบนคอมมิตสุดท้ายจะถูกเปลี่ยนกลับ - คอมมิตใด ๆ สามารถเปลี่ยนกลับได้)

คำถามปิด

คุณต้องทำอย่างอื่นหรือไม่?

A git revertเป็นเพียงการกระทำอื่นดังนั้นเช่นกดไปที่รีโมตเพื่อให้ผู้ใช้รายอื่นสามารถดึง / ดึง / รวมการเปลี่ยนแปลงและคุณทำเสร็จแล้ว

คุณต้องยอมรับการเปลี่ยนแปลงที่ทำกลับไปหรือเปลี่ยนกลับโดยตรงกับ repo หรือไม่?

git revert มีการกระทำ - ไม่มีขั้นตอนพิเศษสมมติย้อนกลับการกระทำเพียงครั้งเดียวคือสิ่งที่คุณอยากจะทำ

แน่นอนว่าคุณจะต้องผลักดันอีกครั้งและอาจประกาศให้ทีมทราบ

อันที่จริง - หากรีโมตอยู่ในสถานะที่ไม่เสถียร - การสื่อสารกับทีมที่เหลือว่าพวกเขาจำเป็นต้องดึงเพื่อรับการแก้ไข (การคืนค่าคอมมิต) จะเป็นสิ่งที่ถูกต้อง :)


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

ฉันมักจะพบว่ามันดีกว่าเสมอที่จะหลีกเลี่ยงการกระทำกับมันเพียงเพื่อตรวจสอบการเปลี่ยนแปลงก่อนและฉันใช้git revert -n <commitToRevet> หรือ git revert --no-commit <commitToRevet>
Eklavyaa

2
แค่อยากจะบอกว่าหลังจากหลายปีบน stackoverflow ฉันคิดว่านี่อาจเป็นหนึ่งในคำตอบที่ดีที่สุดที่ฉันเคยเจอ ตัวอย่างและคำอธิบายที่ยอดเยี่ยมขอบคุณ
user3344977

ฉันมาที่นี่โดยคาดหวังว่าจะได้รับข้อมูลเพิ่มเติมบางอย่างเช่น TLDR ของraw.githubusercontent.com/git/git/master/Documentation/howto/…
wviana

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

35

ใช้ git revert ดังนี้:

git revert <insert bad commit hash here>

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

ขั้นตอนหลังจากนั้นเหมือนกับคอมมิตอื่น ๆ


ความแตกต่างระหว่าง "ย้อนกลับคอมมิต" และ "กลับไปเป็นคอมมิต" นั้นละเอียดมากพอที่ฉันจะต่อสู้กับคำสั่งนี้มาหลายปี คำอธิบายของคุณแก้ไขให้ฉันทันที ขอบคุณ!
claviska

24

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

โดยเฉพาะอย่างยิ่งคนที่จะใช้ในการ SVN หรือ P4 ที่ต้องการที่จะทิ้งการเปลี่ยนแปลงปราศจากข้อผูกมัดไปยังแฟ้มมักจะเข้าถึงสำหรับก่อนที่จะถูกบอกว่าพวกเขาต้องการจริงrevertreset

ในทำนองเดียวกันrevertเทียบเท่าใน VCSes อื่น ๆ มักจะเรียกว่าrollbackหรือสิ่งที่คล้ายกัน - แต่ "ย้อนกลับ" ยังสามารถหมายถึง "ฉันต้องการที่จะสมบูรณ์ทิ้งไม่กี่กระทำที่ผ่านมา" ซึ่งเป็นที่เหมาะสมสำหรับการแต่ไม่reset revertดังนั้นจึงมีความสับสนมากมายที่ผู้คนรู้ว่าพวกเขาต้องการทำอะไร แต่ไม่ชัดเจนว่าพวกเขาควรใช้คำสั่งใด

สำหรับคำถามจริงของคุณเกี่ยวกับการเปลี่ยนกลับ ...

โอเคคุณจะใช้ git revert แต่อย่างไร

git revert first-bad-commit..last-bad-commit

และหลังจากรัน git revert แล้วคุณต้องทำอย่างอื่นหรือไม่? คุณต้องยอมรับการเปลี่ยนแปลงที่ทำกลับไปหรือเปลี่ยนกลับเป็นการกระทำโดยตรงกับ repo หรืออะไร ??

ตามค่าเริ่มต้นระบบgit revertจะแจ้งให้คุณป้อนข้อความคอมมิตจากนั้นส่งผลลัพธ์ สิ่งนี้สามารถลบล้างได้ ฉันอ้างหน้าคน :

- แก้ไข

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

- ไม่ผูกมัด

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

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

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


git revert first-bad-commit..last-bad-commit: git revert parent-of-first-bad-commit..last-bad-commitผมคิดว่านี้ควรจะเป็น
user1071847

10

คำถามค่อนข้างเก่า แต่การย้อนกลับยังคงทำให้ผู้คนสับสน (เช่นฉัน)

ในฐานะมือใหม่หลังจากลองผิดลองถูก (มีข้อผิดพลาดมากกว่าการทดลอง) ฉันมีประเด็นสำคัญ:

  • git revertต้องใช้รหัสของการกระทำที่คุณต้องการลบเก็บไว้ในประวัติของคุณ

  • git resetต้องมีการคอมมิตที่คุณต้องการเก็บไว้และจะลบทุกอย่างออกจากประวัติในภายหลัง

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

เพื่อให้ชัดเจนยิ่งขึ้นด้วยบันทึกดังนี้:

# git log --oneline

cb76ee4 wrong
01b56c6 test
2e407ce first commit

โดยค่าเริ่มต้นการใช้git revert cb76ee4จะนำไฟล์ของคุณกลับไปที่ 01b56c6 และจะเพิ่มข้อผูกพันเพิ่มเติมในประวัติของคุณ:

8d4406b Revert "wrong"
cb76ee4 wrong
01b56c6 test
2e407ce first commit

git reset 01b56c6 จะนำไฟล์ของคุณกลับไปที่ 01b56c6 แทนและจะล้างคอมมิตอื่น ๆ หลังจากนั้นจากประวัติของคุณ:

01b56c6 test
2e407ce first commit

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


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

1

ฉันย้อนกลับการคอมมิทสองสามครั้งโดยเรียกใช้ 'git revert คอมมิต id' เช่น:

git revert b2cb7c248d416409f8eb42b561cbff91b0601712

จากนั้นฉันได้รับแจ้งให้ทำการเปลี่ยนกลับ (เช่นเดียวกับที่คุณทำเมื่อเรียกใช้ 'คอมมิต') โปรแกรมเทอร์มินัลเริ่มต้นของฉันคือ Vim ดังนั้นฉันจึงวิ่ง:

:wq 

ในที่สุดฉันก็ผลักการเปลี่ยนแปลงไปยังที่เก็บด้วย:

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