ฉันจะรีเซ็ตหรือแปลงไฟล์เป็นการแก้ไขเฉพาะได้อย่างไร


4514

ฉันได้ทำการเปลี่ยนแปลงบางอย่างกับไฟล์ที่ถูกคอมมิตสองสามครั้งเป็นส่วนหนึ่งของกลุ่มของไฟล์ แต่ตอนนี้ต้องการรีเซ็ต / ย้อนกลับการเปลี่ยนแปลงในไฟล์กลับไปเป็นเวอร์ชันก่อนหน้า

ฉันได้ทำgit logพร้อมกับ a git diffเพื่อค้นหาการแก้ไขที่ฉันต้องการ แต่เพียงแค่ไม่รู้ว่าจะนำไฟล์กลับสู่สถานะเดิมในอดีตได้อย่างไร


11
หลังจากที่เปลี่ยนกลับอย่าลืมเมื่อตรวจสอบ --cached ลิงก์git diff
Geoffrey Hale

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

คำตอบ:


6133

สมมติว่าแฮชของการกระทำที่คุณต้องการคือc5f567:

git checkout c5f567 -- file1/to/restore file2/to/restore

คอมไพล์เช็คเอาหน้าคนให้ข้อมูลเพิ่มเติม

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

git checkout c5f567~1 -- file1/to/restore file2/to/restore

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


12
@shadowhand: มีวิธีที่จะย้อนกลับหรือไม่ดังนั้นจึงเป็นรุ่นหลังจากนี้หรือไม่
aliteralmind

16
@aliteralmind: ไม่น่าเสียดายที่สัญกรณ์ทางลัดประวัติ Git นั้นย้อนกลับไปในประวัติศาสตร์เท่านั้น
Greg Hewgill

46
หากคุณจะใช้ชื่อสาขาสำหรับabcde (เช่นdevelop) คุณจะต้องการgit checkout develop -- file/to/restore(สังเกตเครื่องหมายขีดกลางสองตัว)
Ohad Schneider

8
@alteralmind: อันที่จริงแล้วใช่มีวิธีที่จะทำ: "บันทึก git - ย้อนกลับ -1 --ancestry-path yourgitrev .. master" แล้วใช้ตัวเลือกที่เหมาะสมเพื่อรับ git rev - การทดสอบเส้นทางจะ "วาดเส้น" ระหว่างสองคอมมิทและ -1 จะแสดงให้คุณเห็นเพียงเวอร์ชั่นเดียวและ - กลับจะทำให้แน่ใจว่ารายการแรกที่ปล่อยออกมานั้นเก่าที่สุด
Chris Cogdon

6
โดยส่วนตัวแล้วฉันคิดว่า HEAD ^ พิมพ์ง่ายกว่า HEAD ~ 1 :)
juzzlin

606

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

git diff <commit hash> <filename>

จากนั้นให้ย้อนกลับไฟล์ที่ระบุเป็นการกระทำโดยใช้คำสั่งรีเซ็ต:

git reset <commit hash> <filename>

คุณอาจจำเป็นต้องใช้--hardตัวเลือกหากคุณมีการปรับเปลี่ยนท้องถิ่น

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

git checkout <commit hash>
git checkout -b <new branch name>

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

git checkout <my branch>
git rebase master
git checkout master
git merge <my branch>

7
คำสั่ง 'git checkout <commit hash>' ให้ฉันย้อนกลับเวอร์ชันเก่าของโครงการนี้ซึ่งฉันกำลังค้นหา Thanks Chris
27414 vidur punj

48
หากต้องการคืนค่าไฟล์git checkout <commit hash> <filename>ทำงานได้ดีกว่าสำหรับฉันมากกว่าgit reset
Motti Strom

3
ฉันต้องการไฟล์รุ่นแรกเพราะฉันเขียนทับ 150 บรรทัดโดยคัดลอก / วางไม่ดี git checkout <commit hash> <filename>ทำงานให้ฉัน นี่ไม่ควรเป็นคำตอบที่ได้รับการยอมรับ IMHO git resetไม่ได้.
harperville

24
ไม่สามารถใช้git resetเพื่อรีเซ็ตไฟล์เดียวคุณจะได้รับข้อผิดพลาดfatal: Cannot do hard reset with paths
slier

13
อะไร slier กล่าวว่า: git reset --hard <commit hash> <filename>คุณไม่สามารถ ข้อผิดพลาดนี้จะfatal: Cannot do hard reset with paths.เกิดขึ้นกับสิ่งที่ Motti Strom กล่าว: ใช้งานgit checkout <commit hash> <filename>
Hawkeye Parker

366

คุณสามารถใช้การอ้างอิงใด ๆ กับคอมมิทคอมมิทรวมถึง SHA-1 หากสะดวกที่สุด ประเด็นก็คือคำสั่งจะเป็นดังนี้:

git checkout [commit-ref] -- [filename]


22
อะไรคือความแตกต่างระหว่างคำตอบนี้ซึ่งมี--และคำตอบที่ยอมรับซึ่งไม่ได้?
2rs2ts

80
ในคอมไพล์ '-' ก่อนรายการไฟล์จะบอกคอมไพล์ว่าอาร์กิวเมนต์ถัดไปทั้งหมดควรถูกตีความเป็นชื่อไฟล์ไม่ใช่ชื่อสาขาหรืออย่างอื่น บางครั้งมันเป็น disambiguator ที่เป็นประโยชน์
foxxtrot

49
'-' ไม่เพียง แต่เป็นแบบแผนคอมไพล์เท่านั้น แต่ยังมีบางสิ่งที่คุณพบในหลาย ๆ ที่บนบรรทัดรับคำสั่ง * nix rm -- -f(ลบไฟล์ชื่อ-f) น่าจะเป็นตัวอย่างที่ยอมรับ รายละเอียดเพิ่มเติมได้ที่นี่
Hawkeye Parker

7
เพียงแค่เพิ่มสิ่งที่ @HawkeyeParker กล่าวว่า rmคำสั่งจะใช้ getopt (3) เพื่อแยกวิเคราะห์อาร์กิวเมนต์ getoptเป็นคำสั่งในการแยกวิเคราะห์คำสั่งอาร์กิวเมนต์ gnu.org/software/libc/manual/html_node/Getopt.html
Devy

2
@ ฮันนี่ใช่นั่นคือสิ่งที่ฉันหมายถึงและใช่อาจไม่ธรรมดาเลย ฉันเคยเห็นตัวอย่างในสถานที่ต่าง ๆ บางทีอาจจะทำให้เป็นที่จดจำได้: rm -f เป็นที่รู้จักกันดีว่าน่ากลัว / อันตราย แต่ประเด็นก็คือใน * nix ชื่อไฟล์สามารถเริ่มต้นด้วย '-' และสิ่งนี้จะสร้างความสับสนให้กับล่ามบรรทัดคำสั่งต่าง ๆ ซึ่งเมื่อพวกเขาเห็น '-' คาดว่าจะมีตัวเลือกคำสั่งให้ติดตาม อาจเป็นไฟล์ใด ๆ ที่ขึ้นต้นด้วย '-' เช่น "-mySpecialFile"
Hawkeye Parker

288
git checkout -- foo

จะรีเซ็ตfooเป็น HEAD นอกจากนี้คุณยังสามารถ:

git checkout HEAD^ foo

สำหรับการแก้ไขครั้งหลัง ฯลฯ


12
ฉันขอแนะนำให้ใช้ไวยากรณ์git checkout -- fooเพื่อหลีกเลี่ยงข้อผิดพลาดหากfooเป็นสิ่งพิเศษ (เช่นไดเรกทอรีหรือไฟล์ที่เรียกว่า-f) ด้วย git หากคุณไม่แน่ใจให้เติมคำนำหน้าไฟล์และไดเรกทอรีทั้งหมดด้วยอาร์กิวเมนต์พิเศษ--เสมอ
Mikko Rantalainen

8
หมายเหตุเพิ่มเติมเกี่ยวกับความคิดเห็นของ Mikko: --ไม่ใช่คำสั่ง git และไม่พิเศษสำหรับ git มันเป็น bash ในตัวเพื่อบ่งบอกถึงตัวเลือกคำสั่งในตอนท้าย คุณสามารถใช้มันกับคำสั่งทุบตีอื่น ๆ ได้เช่นกัน
matthaeus

14
@matthaeus มันไม่เฉพาะเจาะจงกับการทุบตีหรือคุณลักษณะของเชลล์เลย เป็นแบบแผนที่นำมาใช้ในคำสั่งต่าง ๆ (และสนับสนุนโดย getopt)
Greg Hewgill

2
ไม่--เป็นไม่ builtin คำพิเศษในการทุบตี แต่มันเป็นวิธีการทั่วไปที่ได้รับการสนับสนุนจากตัวแยกวิเคราะห์บรรทัดคำสั่งจำนวนมากและใช้โดย CLIs จำนวนมากรวมถึง git
Emil Lundberg

123

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

git checkout HEAD file/to/restore

2
อะไรคือความแตกต่างระหว่างนี้ (ไฟล์เช็คเอาต์ git HEAD / to / restore) และ git reset - ฮาร์ดไฟล์ / to / restore ???
Motti Shneor

2
1) ง่ายต่อการจดจำวิธีทั่วไปมากขึ้น 2) ไม่ต้องกังวลกับการกด Enter ก่อนป้อนชื่อไฟล์
Roman Susi

105

ฉันมีปัญหาเดียวกันในขณะนี้และฉันพบคำตอบนี้ง่ายที่สุดที่จะเข้าใจ ( commit-refเป็นค่า SHA ของการเปลี่ยนแปลงในบันทึกที่คุณต้องการกลับไป):

git checkout [commit-ref] [filename]

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


91

หากคุณรู้ว่าคุณต้องย้อนกลับมากี่ครั้งคุณสามารถใช้:

git checkout master~5 image.png

สมมติว่าคุณอยู่ในmasterสาขาและรุ่นที่คุณต้องการคือ 5 คอมมิชชันย้อนกลับ


80

ฉันคิดว่าฉันพบแล้ว .... จากhttp://www-cs-students.stanford.edu/~blynn/gitmagic/ch02.html

บางครั้งคุณเพียงต้องการย้อนกลับและลืมเกี่ยวกับการเปลี่ยนแปลงทุกอย่างผ่านจุดหนึ่งเพราะพวกเขาผิดทั้งหมด

เริ่มกับ:

$ git log

ซึ่งแสดงรายการการคอมมิทล่าสุดและแฮช SHA1

ถัดไปพิมพ์:

$ git reset --hard SHA1_HASH

เพื่อเรียกคืนสถานะเป็นการกระทำที่กำหนดและลบการกระทำใหม่ทั้งหมดจากบันทึกอย่างถาวร


24
Git ไม่เคยลบอะไรเลย การกระทำเดิมของคุณยังคงอยู่ที่นั่น แต่ถ้าไม่มีปลายแขนชี้ไปที่พวกเขาพวกเขาจะไม่สามารถเข้าถึงได้อีกต่อไป การอ้างอิง git จะยังคงแสดงจนกว่าคุณจะล้างที่เก็บของคุณด้วย git-gc
Bombe

1
@Bombe: ขอบคุณสำหรับข้อมูล ฉันตรวจสอบไฟล์รุ่นเก่าแล้ว หลังจากอ่านความคิดเห็นของคุณฉันสามารถใช้ "gitref" เพื่อค้นหาแฮช SHA1 บางส่วนและใช้ "ชำระเงิน" เพื่อกลับไปใช้เวอร์ชันล่าสุด ผู้ใช้คอมไพล์คนอื่น ๆ อาจพบว่าข้อมูลนี้มีประโยชน์
Winston C. Yang

4
อาจตามด้วยgit push --force
bshirley

4
หากคุณมีการเปลี่ยนแปลงที่ไม่มีข้อผูกมัดคุณจะสูญเสียมันหากทำการตั้งค่า git
ฮาร์ด

5
@Bombe - "Git ไม่เคยลบอะไรเลยคำมั่นสัญญาเก่าของคุณยังคงอยู่ที่นั่น แต่ถ้าไม่มีปลายกิ่งชี้ไปที่พวกมัน - แต่การกระทำเช่นนี้จะถูกตัดหลังจากเวลาที่กำหนดดังนั้น "Git ไม่เคยลบอะไรเลย" จึงไม่เป็นความจริง
Bulwersator

61

สิ่งนี้ใช้ได้กับฉัน:

git checkout <commit hash> file

จากนั้นส่งการเปลี่ยนแปลง:

git commit -a

54

คุณต้องระวังเมื่อคุณพูดว่า "ย้อนกลับ" หากคุณเคยมีไฟล์หนึ่งเวอร์ชันที่คอมมิท $ A และหลังจากนั้นทำการเปลี่ยนแปลงสองครั้งในสองแบบที่แยกกันคือคอมมิท $ B และ $ C (ดังนั้นสิ่งที่คุณเห็นคือการทำซ้ำไฟล์ครั้งที่สาม) และถ้าคุณพูดว่า " ฉันต้องการย้อนกลับไปเป็นคนแรก "คุณหมายถึงมันจริงเหรอ?

หากคุณต้องการกำจัดการเปลี่ยนแปลงทั้งการวนซ้ำครั้งที่สองและครั้งที่สามมันง่ายมาก:

$ git checkout $A file

และจากนั้นคุณยอมรับผลลัพธ์ คำสั่งถามว่า "ฉันต้องการตรวจสอบไฟล์จากสถานะที่บันทึกโดยการส่งมอบ $ A"

ในทางกลับกันสิ่งที่คุณหมายถึงคือกำจัดการเปลี่ยนแปลงที่เกิดซ้ำครั้งที่สอง (เช่นการส่งมอบ $ B) ที่นำเข้ามาในขณะที่การรักษาสิ่งที่ $ C กระทำต่อไฟล์คุณต้องการเปลี่ยน $ B อีกครั้ง

$ git revert $B

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


ฉันทำสิ่งนี้ แต่จากนั้น "ล็อกไฟล์ git" จะบอกว่าฉันอยู่ในการกระทำเดิม HEAD ดูเหมือนว่า "เช็คเอาต์คอมไพล์" ล้มเหลว อย่างไรก็ตามสถานะ git แสดงให้เห็นว่าไฟล์นั้นมีการเปลี่ยนแปลงจริงและ "git diff - staged file" จะแสดงการเปลี่ยนแปลงที่เกิดขึ้นจริง นอกจากนี้ "สถานะคอมไพล์" แสดงให้เห็นว่าไฟล์มีการเปลี่ยนแปลงเช่นกัน ดังนั้นอย่าใช้ "git log" ที่นี่เพื่อติดตามว่าไฟล์ใดเปลี่ยนแปลง
Frederick Ollinger

37

ตลกขบขันgit checkout fooจะไม่ทำงานหากสำเนาการทำงานที่อยู่ในไดเรกทอรีชื่อfoo; อย่างไรก็ตามทั้งสองgit checkout HEAD fooและgit checkout ./fooจะ:

$ pwd
/Users/aaron/Documents/work/foo
$ git checkout foo
D   foo
Already on "foo"
$ git checkout ./foo
$ git checkout HEAD foo

26
หรือgit checkout -- foo
knittl

32

นี่คือวิธีการrebaseทำงาน:

git checkout <my branch>
git rebase master
git checkout master
git merge <my branch>

สมมติว่าคุณมี

---o----o----o----o  master
    \---A----B       <my branch>

สองคำสั่งแรก ... ส่ง git checkout git rebase master

... ตรวจสอบสาขาการเปลี่ยนแปลงที่คุณต้องการใช้กับmasterสาขา rebaseคำสั่งใช้เวลากระทำจาก<my branch>(ที่ไม่พบในmaster) และ reapplies masterพวกเขาที่หัวของ ในคำอื่น ๆ ผู้ปกครองแรกกระทำใน<my branch>ไม่เป็นก่อนหน้านี้กระทำในmasterประวัติศาสตร์ masterแต่หัวปัจจุบันของ คำสั่งสองคำนั้นเหมือนกับ:

git rebase master <my branch>

มันอาจจะง่ายกว่าที่จะจำคำสั่งนี้เพราะทั้ง "สาขา" และ "แก้ไข" สาขามีความชัดเจน

. ผลลัพธ์ประวัติครั้งสุดท้ายคือ:

---o----o----o----o   master
                   \----A'----B'  <my branch>

คำสั่งสุดท้ายสองคำ ...

git checkout master
git merge <my branch>

... ทำการรวมอย่างรวดเร็วเพื่อนำ<my branch>การเปลี่ยนแปลงทั้งหมดไปmasterใช้ โดยไม่ต้องขั้นตอนนี้ rebase masterกระทำไม่ได้รับการบันทึก ผลลัพธ์สุดท้ายคือ:

---o----o----o----o----A'----B'  master, <my branch>

masterและทั้งการอ้างอิง<my branch> B'นอกจากนี้จากจุดนี้จะปลอดภัยในการลบการ<my branch>อ้างอิง

git branch -d <my branch>

26

ในฐานะของ v2.23.0 คอมไพล์มีใหม่คอมไพล์เรียกคืนวิธีการซึ่งควรจะถือว่าเป็นส่วนหนึ่งของสิ่งที่git checkoutเป็นความรับผิดชอบ (แม้คำตอบที่ได้รับการยอมรับกล่าวว่าgit checkoutค่อนข้างสับสน) ดูไฮไลท์ของการเปลี่ยนแปลงในบล็อก GitHub

พฤติกรรมเริ่มต้นของคำสั่งนี้คือการคืนค่าสถานะของแผนภูมิการทำงานที่มีเนื้อหามาจากsourceพารามิเตอร์ (ซึ่งในกรณีของคุณจะเป็นแฮชการกระทำ)

ดังนั้นตามคำตอบของ Greg Hewgill (สมมติว่าแฮชการกระทำc5f567) คำสั่งจะเป็นดังนี้:

git restore --source=c5f567 file1/to/restore file2/to/restore

หรือถ้าคุณต้องการกู้คืนไปยังเนื้อหาของการคอมมิทหนึ่งก่อน c5f567:

git restore --source=c5f567~1 file1/to/restore file2/to/restore

24

รีเซ็ตหัวแรกสำหรับไฟล์เป้าหมาย

git reset HEAD path_to_file

การชำระเงินที่สองที่ไฟล์

git checkout -- path_to_file

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

ใช่ฉันต้องการเรียกใช้คำสั่งที่ 2 เท่านั้น กดไลค์
javaPlease42

22

git-aliases, awk และ shell-functions เพื่อช่วยเหลือ!

git prevision <N> <filename>

ที่เป็นจำนวนของการแก้ไขของแฟ้มที่จะย้อนกลับสำหรับแฟ้ม<N> ตัวอย่างเช่นหากต้องการชำระเงินการแก้ไขก่อนหน้านี้ทันทีของไฟล์เดียวให้เรียกใช้<filename>
x/y/z.c

git prevision -1 x/y/z.c

Git prevision ทำงานอย่างไร?

เพิ่มสิ่งต่อไปนี้ใน gitconfig

[alias]
        prevision = "!f() { git checkout `git log --oneline $2 |  awk -v commit="$1" 'FNR == -commit+1 {print $1}'` $2;} ;f"

คำสั่งนั้นเป็นพื้น

  • ดำเนินการgit logกับไฟล์ที่ระบุและ
  • เลือก commit-id ที่เหมาะสมในประวัติของไฟล์และ
  • รัน a git checkoutถึง commit-id สำหรับไฟล์ที่ระบุ

สิ่งสำคัญที่ทุกคนจะต้องทำด้วยตนเองในสถานการณ์นี้
ถูกห่อหุ้มไว้ในคอมไพล์ git-alias ที่สวยงามและมีประสิทธิภาพ - git-prevision


20

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

eg revert foo/bar foo/baz


1
eg revert --in REVISON -- FILENAMEมันควรจะเป็น --inเป็นสิ่งสำคัญ สำหรับผู้ใช้ Windows ที่นั่น: เปิด git bash echo %PATHปฏิบัติ binเส้นทางแรกที่ควรจะอยู่ในไดเรกทอรีผู้ใช้ของคุณที่ลงท้ายด้วย สร้างเส้นทางนั้น ร้านค้าเช่นมี egชื่อมัน eg.txtไม่
koppor

20

ในกรณีที่คุณต้องการเปลี่ยนไฟล์กลับเป็นการกระทำก่อนหน้า (และไฟล์ที่คุณต้องการเปลี่ยนกลับที่กระทำไปแล้ว) คุณสามารถใช้

git checkout HEAD^1 path/to/file

หรือ

git checkout HEAD~1 path/to/file

จากนั้นเพียงแค่จัดวางและเวอร์ชั่น "ใหม่"

ด้วยความรู้ที่ว่าคอมมิชชันสามารถมีสองพาเรนต์ในกรณีของการผสานคุณควรรู้ว่า HEAD ^ 1 เป็นพาเรนต์แรกและ HEAD ~ 1 เป็นพาเรนต์ที่สอง

ทั้งสองจะทำงานถ้ามีผู้ปกครองเพียงคนเดียวในต้นไม้


19

git checkout $revision -- $fileข้อเสนอแนะหลายคนที่นี่ส่วนใหญ่ตามสายของ ทางเลือกที่คลุมเครือสองอย่าง:

git show $revision:$file > $file

และฉันก็ใช้มันหลายอย่างเพื่อดูเวอร์ชันชั่วคราว:

git show $revision:$file

หรือ

git show $revision:$file | vim -R -

(OBS: $fileจำเป็นต้องขึ้นต้นด้วย./ถ้าเป็นเส้นทางที่สัมพันธ์กันเพื่อgit show $revision:$fileให้ทำงานได้)

และยิ่งแปลก ๆ :

git archive $revision $file | tar -x0 > $file

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

18

แต่โปรดทราบว่าgit checkout ./fooและgit checkout HEAD ./foo ไม่ได้ว่าสิ่งเดียวกัน; กรณีในจุด:

$ echo A > foo
$ git add foo
$ git commit -m 'A' foo
Created commit a1f085f: A
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 foo
$ echo B >> foo
$ git add foo
$ echo C >> foo
$ cat foo
A
B
C
$ git checkout ./foo
$ cat foo
A
B
$ git checkout HEAD ./foo
$ cat foo
A

( addขั้นตอนที่สองไฟล์ในดัชนี แต่ไม่ได้รับการมุ่งมั่น)

Git checkout ./fooวิธีการย้อนกลับเส้นทาง./fooจากดัชนี ; การเพิ่มHEADสั่งให้ Git เปลี่ยนเส้นทางนั้นในดัชนีเป็นการ HEADแก้ไขก่อนที่จะทำเช่นนั้น


14

สำหรับฉันไม่มีคำตอบที่ดูเหมือนชัดเจนจริงๆและดังนั้นฉันต้องการเพิ่มของฉันซึ่งดูเหมือนง่ายสุด

ฉันมีการกระทำabc1และหลังจากที่ฉันได้ทำหลายคน (หรือการเปลี่ยนแปลงอย่างใดอย่างหนึ่ง) file.txtไปยังแฟ้ม

ตอนนี้พูดได้ว่าผม messed up บางสิ่งบางอย่างในแฟ้มและฉันต้องการที่จะกลับไปก่อนหน้านี้กระทำการfile.txtabc1

1. git checkout file.txt: สิ่งนี้จะลบการเปลี่ยนแปลงในเครื่องหากคุณไม่ต้องการ

2. git checkout abc1 file.txt: สิ่งนี้จะนำไฟล์ของคุณไปสู่เวอร์ชันที่คุณต้องการ

3. git commit -m "Restored file.txt to version abc1": นี่จะกระทำการพลิกกลับของคุณ

  1. git push : สิ่งนี้จะผลักดันทุกอย่างในที่เก็บระยะไกล

ระหว่างขั้นตอนที่ 2 และ 3 ของหลักสูตรคุณสามารถทำgit statusเพื่อเข้าใจสิ่งที่เกิดขึ้น โดยปกติแล้วคุณจะเห็นเพิ่มไว้แล้วและนั่นคือเหตุผลที่มีความต้องการของไม่มีfile.txtgit add


2
ตกลงดังนั้นฉันเดาขั้นตอนที่ 1 และ 2 เป็นพิเศษร่วมกัน: ถ้า abc1 เป็นความมุ่งมั่นครั้งสุดท้ายของคุณไม่จำเป็นต้องมี 2 และถ้ามีความมุ่งมั่นอื่น ๆ หลังจาก abc1 คุณสามารถทำได้โดยตรง 2
Jean Paul

13
  1. Git เปลี่ยนไฟล์กลับเป็นการกระทำที่เฉพาะเจาะจง
git checkout Last_Stable_commit_Number -- fileName

2.Git แปลงไฟล์เป็นสาขาเฉพาะ

git checkout branchName_Which_Has_stable_Commit fileName

11

ในการไปยังไฟล์เวอร์ชันคอมมิชชันก่อนหน้านี้รับหมายเลขการคอมมิชชันพูด eb917a1 แล้ว

git checkout eb917a1 YourFileName

หากคุณเพียงแค่ต้องย้อนกลับไปยังรุ่นที่ได้รับการยอมรับล่าสุด

git reset HEAD YourFileName
git checkout YourFileName

การดำเนินการนี้จะนำคุณไปสู่สถานะที่ยืนยันล่าสุดของไฟล์



10

คำตอบมากมายที่นี่อ้างว่าใช้git reset ... <file>หรือgit checkout ... <file>แต่โดยการทำเช่นนั้นคุณจะสูญเสียการปรับเปลี่ยนทุกอย่างที่<file>เกิดขึ้นหลังจากการคอมมิทที่คุณต้องการเปลี่ยนกลับ

หากคุณต้องการที่จะเปลี่ยนแปลงการเปลี่ยนกลับจากที่หนึ่งกระทำในไฟล์เดียวเท่านั้นเช่นเดียวกับที่git revertจะทำ แต่สำหรับไฟล์เดียว (หรือพูดย่อยของกระทำไฟล์), ฉันขอแนะนำให้ใช้ทั้งสองgit diffและgit applyเช่นเดียวกับที่ (มี<sha>= กัญชาของ ความมุ่งมั่นที่คุณต้องการเปลี่ยนกลับ):

git diff <sha>^ <sha> path/to/file.ext | git apply -R

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

แน่นอนว่ามันจะไม่ทำงานหากสายการย้อนกลับได้รับการแก้ไขโดยการกระทำใด ๆ ระหว่าง<sha1>และHEAD(ความขัดแย้ง)


นั่นควรเป็นคำตอบที่ได้รับการอนุมัติ ฉันขอแนะนำเวอร์ชั่นที่เรียบง่ายเล็กน้อยได้git show -p <sha> path/to/file.ext|git apply -R
Amaury D

คุณสามารถใช้<sha>^!แทน<sha>^ <sha>
cambunctious

8

ใช้git logเพื่อรับคีย์แฮชสำหรับเวอร์ชันเฉพาะจากนั้นใช้git checkout <hashkey>

หมายเหตุ: อย่าลืมพิมพ์แฮชก่อนอันสุดท้าย แฮชสุดท้ายชี้ตำแหน่งปัจจุบันของคุณ (HEAD) และไม่เปลี่ยนแปลงอะไรเลย


7

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

cd <working copy>
git revert master

จะยกเลิกการกระทำครั้งสุดท้ายที่ดูเหมือนจะทำ

เอียน


7

คุณสามารถทำได้ใน 4 ขั้นตอน:

  1. ย้อนกลับการคอมมิททั้งหมดด้วยไฟล์ที่คุณต้องการย้อนกลับโดยเฉพาะ - มันจะสร้างการคอมมิทใหม่ในสาขาของคุณ
  2. ซอฟต์รีเซ็ตที่คอมมิท - ลบการคอมมิตและย้ายการเปลี่ยนแปลงไปยังพื้นที่ทำงาน
  3. handpick ไฟล์เพื่อย้อนกลับและคอมมิท
  4. ปล่อยไฟล์อื่นทั้งหมดในพื้นที่ทำงานของคุณ

สิ่งที่คุณต้องพิมพ์ในเครื่องเทอร์มินัลของคุณ :

  1. git revert <commit_hash>
  2. git reset HEAD~1
  3. git add <file_i_want_to_revert> && git commit -m 'reverting file'
  4. git checkout .

โชคดี


นั่นจะไม่เปลี่ยนการเปลี่ยนแปลงทั้งหมดใช่ไหม
arcee123

1
@ arcee123 ใช่ แต่การรีเซ็ตภายหลังจะยกเลิกการเปลี่ยนแปลงกลับทั้งหมด ปัญหาคือว่าgit-revertทำงานเฉพาะใน repo ทั้งหมดดังนั้นเพื่อชดเชยเราต้องยกเลิกทุกอย่างอื่น
ทิโมธี

2
ฉันขอแนะนำให้ใช้: 1. git revert --no-commit <commit_hash>2. git reset HEADสิ่งนี้จะบันทึกการกระทำพิเศษที่ลอยไปมาและทำการเปลี่ยนแปลงทั้งหมดในไดเรกทอรีการทำงานของคุณเท่านั้น
Timothy

คำตอบของ @greg-hewgill ดีกว่าและตรงตาม อันนี้มีหมัดและไม่ควรใช้
Daniel Tranca

ตรงนี้เป็นสิ่งที่จำเป็นสำหรับการคืนค่าไฟล์จริงอย่างแท้จริง ฉันต้องการเลิกทำการเปลี่ยนแปลงกับไฟล์บางไฟล์จากการคอมมิชชันก่อนหน้าซึ่งถูกผลักไปยังที่เก็บรีโมตแล้ว ฉันย้อนกลับตั้งค่าและส่งผลลัพธ์: git revert _oldcommit_ --no-commit git reset -- _unchanged1_ _unchanged2_ ... git commit -m "branch without changes to specific files"ปลายกิ่งใหม่สะท้อนการเปลี่ยนแปลงทั้งหมดยกเว้นไฟล์ย้อนกลับ
Suncat2000

7

นี่เป็นขั้นตอนที่ง่ายมาก เช็คเอาต์ไฟล์ไปยังคอมมิท id ที่เราต้องการ, ที่นี่หนึ่งคอมมิทยอมรับก่อนหน้านี้, จากนั้นเพียงคอมไพล์คอมมิทแก้ไขและทำเสร็จแล้ว

# git checkout <previous commit_id> <file_name>
# git commit --amend

มันมีประโยชน์มาก หากเราต้องการนำไฟล์ใด ๆ ไปยังรหัสการกระทำก่อนหน้านี้ที่ด้านบนของการกระทำเราสามารถทำได้อย่างง่ายดาย


5
git revert <hash>

จะยกเลิกการส่งมอบที่ได้รับ ดูเหมือนว่าคุณคิดว่าgit revertจะส่งผลต่อความมุ่งมั่นล่าสุดเท่านั้น

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


5

หากคุณส่งไฟล์ผิดครั้งสุดท้ายให้ทำตามคำแนะนำ:

  1. แผนผังโอเพ่นซอร์สเปลี่ยนเป็นการกระทำนี้

ต้นไม้โอเพ่นซอร์ส

  1. เปลี่ยนบรรทัดและค้นหาการกระทำของคุณว่าไฟล์ผิดส่งเป็นกระทำ

ป้อนคำอธิบายรูปภาพที่นี่

  1. คุณสามารถดูรายการการเปลี่ยนแปลงที่ทำไว้ รายการไฟล์ในแผนผังต้นกำเนิด
  2. เลือกจากนั้นคลิกที่ปุ่ม ... ด้านขวามือ ... คลิกย้อนกลับไฟล์
  3. จากนั้นคุณสามารถดูได้ที่แท็บสถานะไฟล์ที่ด้านล่างซ้ายมือจากนั้นคลิก unstage:

แท็บสถานะไฟล์

  1. เปิดรหัส visual studio และย้อนกลับโดยยอมรับไฟล์ที่ถูกลบ
  2. หลังจากพวกเขาทั้งหมดคุณสามารถเห็นผลลัพธ์ในการกระทำครั้งสุดท้ายของคุณในต้นไม้ต้นกำเนิด

ป้อนคำอธิบายรูปภาพที่นี่

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