ฉันสามารถแปลงกลับเป็นบางส่วนใน GIT ได้ไหม


156

เป็นไปได้หรือไม่ที่จะคืนค่าไฟล์เดียวหรือการเปลี่ยนแปลงบางอย่างในไฟล์ที่กระทำหลายไฟล์?

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


ไบรอันพาฉันไปถูกทาง ฉันลงเอยด้วยการใช้ git add --patch แล้วใช้ฟังก์ชั่นแก้ไขภายในโปรแกรมแก้ไขเพื่อให้ได้สิ่งที่ฉันต้องการ
คลัตช์

2
ฉันรักสายเกม แต่ผมคิดว่าผมพบว่า"สิทธิ" คำตอบ
ntc2

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

@liridayn คุณอ่านคำตอบทั้งหมดของฉันหรือไม่ ในส่วน "รูปแบบต่างๆ" ฉันอ้างว่าการเพิ่ม--3wayผลลัพธ์ในการรวมความขัดแย้งแทนที่จะไม่ใช้แพทช์
ntc2

คำตอบ:


204

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

git revert <sha-of-bad-commit> --no-commit
git reset   // This gets them out of the staging area
<edit bad file to look like it should, if necessary>
git add <bad-file>
git checkout . // This wipes all the undesired reverts still hanging around in the working copy
git commit

42
หลังจากซอฟต์รีเซ็ตคุณยังสามารถgit add -pเริ่มเซสชันโต้ตอบที่ให้คุณเลือกเพิ่มไฟล์ได้แทนที่จะเป็นไฟล์ทั้งหมด (นอกจากนี้ยังมีgit reset -pการเปลี่ยนแปลงแบบไม่มีการเลือกขั้นตอนน่ารู้ แต่อาจไม่ใช่สิ่งที่คุณต้องการในสถานการณ์นี้)
Stéphan Kochen

1
นี่คือสิ่งที่ฉันกำลังมองหา: เปลี่ยนกลับเป็นสำเนาการทำงานเลือกนักล่าโต้ตอบ คุณสมควรได้รับการจูบผู้ชายที่ใหญ่และเค็ม: *
das_weezul

วิธีการแก้ปัญหาอีกแรงบันดาลใจจากคนนี้จะไปrevert, reset, stash -p(ซ่อน "ยกเลิกที่ฉันไม่ต้องการที่จะทำจริง") addส่วนที่เหลือcommit
Cyril Chapon

82

คุณสามารถใช้ไฟล์เวอร์ชันเก่าแบบโต้ตอบโดยใช้checkoutคำสั่ง

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

git checkout -p COMMIT^ -- FILE_TO_REVERT

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


มีประโยชน์มากถ้าคุณต้องการคืนไฟล์บางส่วนเท่านั้น! โดยทั่วไปจะได้รับชิ้นส่วนจากหัวgit checkout -p path/to/file
falstaff

40

คุณสามารถตรวจสอบไฟล์เก่าที่ดีของไฟล์ที่คุณต้องการคืนค่าด้วยgit checkoutตนเอง ตัวอย่างเช่นหากคุณต้องการเปลี่ยนกลับmy-important-fileเป็นเวอร์ชันabc123เดิมคุณสามารถทำได้

git checkout abc123 -- my-important-file

ตอนนี้คุณมีเนื้อหาเก่า ๆ ของmy-important-fileหลังและสามารถแก้ไขได้หากคุณรู้สึกและทำตามปกติเพื่อทำการคอมมิชชันซึ่งจะย้อนกลับการเปลี่ยนแปลงที่เขาทำ หากมีเพียงบางส่วนของความมุ่งมั่นของเขาที่คุณต้องการเปลี่ยนกลับให้ใช้git add -pเพื่อเลือกล่าสัตว์เพียงไม่กี่ตัวจากแพทช์ที่คุณทำ


19
นี่ไม่ใช่revertคุณเพิ่งนำไฟล์เวอร์ชันเก่ากลับมา ที่เหมาะสมrevertจะลบการแก้ไขการคอมมิตที่ไม่ดีภายในไฟล์แม้ว่าจะได้รับการแก้ไขหลายครั้งตั้งแต่การคอมมิทที่ไม่ดีนั้นและคุณไม่ต้องการสูญเสียการแก้ไขเหล่านั้น
Totor

2
Totor ดูคำตอบของฉัน คุณสามารถใช้ '-p' เพื่อบันทึกการแก้ไข คำตอบนั้นใกล้เคียงกับคำตอบนี้จริงๆ
cmcginty

1
หรือคุณสามารถรวมมันเข้าgit checkout -pกับ
Léo Lam

31

ฉันพบวิธีการทำสิ่งนี้ในรายชื่อผู้รับจดหมายของ Git:

git show <commit> -- <path> | git apply --reverse

ที่มา: http://git.661346.n2.nabble.com/Revert-a-single-commit-in-a-single-file-td6064050.html#a6064406

รูปแบบ

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

git show <commit> -- <path> | git apply --reverse --3way

นอกจากนี้คุณยังสามารถใช้วิธีนี้เพื่อยกเลิกการคอมมิทหลายครั้งได้เช่น

git log -S<string> --patch | git apply --reverse

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

ถ้าคุณได้diff.noprefix=trueตั้งอยู่ในของคุณ~/.gitconfigแล้วคุณจะต้องเพิ่ม-p0ไปยังgit applyคำสั่งเช่น

git show <commit> -- <path> | git apply -p0 --reverse

คำตอบนี้ดีกว่าคำตอบที่ยอมรับ: "ดีกว่าเข้าไปข้างในและยกเลิกการเปลี่ยนแปลงสองไฟล์ในไฟล์นั้น"
เขียนใหม่

ผมอยากที่จะย้อนกลับไปเพียงส่วนหนึ่งของการกระทำเพื่อให้ฉันได้: (1) git show ... > foo.txt (2)แก้ไขfoo.txtเพื่อลบ diffs ที่ฉันต้องการที่จะไม่ย้อนกลับ(3) git apply --reverse foo.txtเพื่อกลับ diffs foo.txtยังระบุไว้ใน
cxw

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