สมมติว่าฉันอยู่ในที่เก็บ Git ฉันลบไฟล์และยืนยันการเปลี่ยนแปลงนั้น ฉันยังคงทำงานและทำภาระกิจเพิ่มเติม จากนั้น ฉันพบว่าฉันต้องกู้คืนไฟล์นั้น

ฉันรู้ว่าฉันสามารถชำระเงินไฟล์โดยใช้git checkout HEAD^ foo.barได้ แต่ฉันไม่รู้จริงๆ ว่าไฟล์นั้นถูกลบไปเมื่อใด

  1. วิธีใดเป็นวิธีที่เร็วที่สุดในการค้นหาการคอมมิตที่ลบชื่อไฟล์ที่กำหนด
  2. วิธีใดเป็นวิธีที่ง่ายที่สุดในการนำไฟล์นั้นกลับเข้าไปในสำเนาการทำงานของฉัน

ฉันหวังว่าฉันจะไม่ต้องเรียกดูบันทึกของฉันเอง ชำระเงินโครงการทั้งหมดสำหรับ SHA ที่กำหนด จากนั้นจึงคัดลอกไฟล์นั้นไปยังจุดชำระเงินของโครงการดั้งเดิมของฉันด้วยตนเอง

ตอบ

ค้นหาการคอมมิตล่าสุดที่ส่งผลต่อเส้นทางที่กำหนด เนื่องจากไฟล์ไม่อยู่ในการคอมมิต HEAD การคอมมิตนี้จึงต้องลบทิ้ง

git rev-list -n 1 HEAD -- <file_path>

จากนั้นเช็คเอาต์เวอร์ชันที่คอมมิทก่อน โดยใช้^สัญลักษณ์คาเร็ต ( )

git checkout <deleting_commit>^ -- <file_path>

หรือในคำสั่งเดียวถ้า$fileเป็นไฟล์ที่เป็นปัญหา

git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file"

หากคุณกำลังใช้ zsh และเปิดใช้งานตัวเลือก EXTENDED_GLOB สัญลักษณ์คาเร็ตจะไม่ทำงาน คุณสามารถใช้~1แทน

git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file"
  1. ใช้git log --diff-filter=D --summaryเพื่อรับคอมมิตทั้งหมดที่มีไฟล์ที่ถูกลบและไฟล์ที่ถูกลบ
  2. ใช้git checkout $commit~1 path/to/file.extเพื่อกู้คืนไฟล์ที่ถูกลบ

$commitค่าของคอมมิตที่คุณพบในขั้นตอนที่ 1 อยู่ที่ไหนเช่นe4cf499627

หากต้องการกู้คืนไฟล์ที่ถูกลบทั้งหมดในโฟลเดอร์ ให้ป้อนคำสั่งต่อไปนี้

git ls-files -d | xargs git checkout --

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

git checkout HEAD -- path/to/file.ext

หากคุณบ้า ให้ใช้git-bisect. นี่คือสิ่งที่ต้องทำ:

git bisect start
git bisect bad
git bisect good <some commit where you know the file existed>

ตอนนี้ได้เวลาเรียกใช้การทดสอบอัตโนมัติแล้ว คำสั่งเชลล์'[ -e foo.bar ]'จะคืนค่า 0 ถ้าfoo.barมี มิฉะนั้น 1 รายการ คำสั่ง "run" git-bisectจะใช้การค้นหาแบบไบนารีเพื่อค้นหาคอมมิตแรกโดยอัตโนมัติเมื่อการทดสอบล้มเหลว มันเริ่มต้นครึ่งทางของช่วงที่กำหนด (จากดีไปไม่ดี) และลดลงครึ่งหนึ่งตามผลการทดสอบที่ระบุ

git bisect run '[ -e foo.bar ]'

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

git bisect reset
git revert <the offending commit>

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

git checkout HEAD^
cp foo.bar /tmp
git bisect reset
cp /tmp/foo.bar .

นามแฝงใหม่ที่ฉันโปรดปรานตามคำตอบของbonyiii (upvoted) และคำตอบของฉันเองเกี่ยวกับ " ส่งอาร์กิวเมนต์ไปยังคำสั่ง Git alias ":

git config alias.restore '!f() { git checkout $(git rev-list -n 1 HEAD -- $1)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- $1)~1 | grep '^D' | cut -f 2); }; f'

ฉันทำไฟล์หาย ถูกลบโดยไม่ได้ตั้งใจสองสามข้อที่แล้วใช่ไหม
เร็ว:

git restore my_deleted_file

วิกฤตพลิกผัน

คำเตือน ด้วย Git 2.23 (Q3 2019) มาคำสั่งทดลองชื่อgit restore(!)
ดังนั้นเปลี่ยนชื่อนามแฝงนี้ (ดังแสดงด้านล่าง)


Robert Daileyเสนอความคิดเห็นโดยใช้นามแฝงต่อไปนี้:

restore-file = !git checkout $(git rev-list -n 1 HEAD -- "$1")^ -- "$1"

และjeganเพิ่มความคิดเห็น :

For setting the alias from the command line, I used this command:

git config --global alias.restore "\!git checkout \$(git rev-list -n 1 HEAD -- \"\$1\")^ -- \"\$1\"" 

หากคุณทราบชื่อไฟล์ นี่เป็นวิธีง่ายๆ ด้วยคำสั่งพื้นฐาน:

แสดงรายการคอมมิตทั้งหมดสำหรับไฟล์นั้น

git log -- path/to/file

คอมมิตล่าสุด (บนสุด) คืออันที่ลบไฟล์ ดังนั้นคุณต้องกู้คืนการคอมมิตที่สองเป็นครั้งสุดท้าย

git checkout {second to last commit} -- path/to/file

ในการกู้คืนไฟล์ที่ถูกลบและคอมมิต:

git reset HEAD some/path
git checkout -- some/path

ได้รับการทดสอบบน Git เวอร์ชัน 1.7.5.4

ฉันมีวิธีแก้ปัญหานี้

  1. รับ id ของการคอมมิตที่ไฟล์ถูกลบโดยใช้วิธีใดวิธีหนึ่งด้านล่าง

    • git log --grep=*word*
    • git log -Sword
    • git log | grep --context=5 *word*
    • git log --stat | grep --context=5 *word* #แนะนำถ้าจำอะไรไม่ค่อยได้
  2. คุณควรได้รับสิ่งที่ชอบ:

commit bfe68bd117e1091c96d2976c99b3bcc8310bebe7 Author: Alexander Orlov Date: Thu May 12 23:44:27 2011 +0200

replaced deprecated GWT class
- gwtI18nKeySync.sh, an outdated (?, replaced by a Maven goal) I18n generation script

commit 3ea4e3af253ac6fd1691ff6bb89c964f54802302 Author: Alexander Orlov Date: Thu May 12 22:10:22 2011 +0200

3 . ตอนนี้ใช้รหัสการคอมมิต bfe68bd117e1091c96d2976c99b3bcc8310bebe7 ทำ:

git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java

ในฐานะที่เป็นกระทำอ้างอิงรหัสกระทำที่ไฟล์นั้นถูกลบไปแล้วคุณจะต้องอ้างอิงกระทำก่อน bfe68b ^1ซึ่งคุณสามารถทำโดยการผนวก ซึ่งหมายความว่า: มอบคอมมิชชันให้ฉันก่อน bfe68b

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

git checkout -- .

แต่ไฟล์ที่ถูกลบของคุณไม่กลับมา คุณเพียงแค่ทำตามคำสั่งต่อไปนี้:

git checkout <file_path>

และโอ้โฮ ไฟล์ของคุณกลับมาแล้ว

git checkout /path/to/deleted.file

git undelete path/to/file.ext

  1. ใส่สิ่งนี้ในของคุณ.bash_profile(หรือไฟล์ที่เกี่ยวข้องอื่น ๆ ที่โหลดเมื่อคุณเปิดเชลล์คำสั่ง):

    git config --global alias.undelete '!sh -c "git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1" -'
    
  2. จากนั้นใช้:

    git undelete path/to/file.ext
    

นามแฝงนี้จะตรวจสอบก่อนเพื่อค้นหาการคอมมิตล่าสุดที่มีไฟล์นี้ จากนั้นจึงทำการเช็คเอาต์ Git ของพาธไฟล์นั้นจากการคอมมิตล่าสุดที่มีไฟล์นี้อยู่ แหล่ง

อันที่จริง คำถามนี้เกี่ยวกับ Git โดยตรง แต่บางคนอย่างฉันทำงานกับเครื่องมือ GUI เช่นWebStorm VCSอื่นนอกเหนือจากการรู้เกี่ยวกับคำสั่ง Git CLI

ผมคลิกขวาบนเส้นทางที่มีไฟล์ที่ถูกลบและจากนั้นไปที่ Git แล้วคลิกที่แสดงประวัติความเป็นมา

ใส่คำอธิบายภาพที่นี่

เครื่องมือ VCS แสดงการฝึกแก้ไขทั้งหมด และฉันสามารถเห็นการคอมมิตและการเปลี่ยนแปลงของแต่ละรายการได้

ใส่คำอธิบายภาพที่นี่

จากนั้นฉันเลือกคอมมิตที่เพื่อนของฉันลบPostAd.jsไฟล์ ตอนนี้ดูด้านล่าง:

ใส่คำอธิบายภาพที่นี่

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

ใส่คำอธิบายภาพที่นี่

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

ในหลายกรณี การใช้coreutils (grep, sed เป็นต้น) ร่วมกับ Git อาจเป็นประโยชน์ ฉันรู้จักเครื่องมือเหล่านี้ค่อนข้างดี แต่ Git น้อยกว่านั้น หากฉันต้องการค้นหาไฟล์ที่ถูกลบ ฉันจะทำดังต่อไปนี้:

git log --raw | grep -B 30 $'D\t.*deleted_file.c'

เมื่อฉันพบการแก้ไข/กระทำ:

git checkout <rev>^ -- path/to/refound/deleted_file.c

เหมือนกับที่คนอื่นๆ ได้กล่าวไว้ก่อนหน้าฉัน

ไฟล์จะถูกกู้คืนไปยังสถานะเดิมก่อนที่จะนำออก อย่าลืมผูกมัดกับแผนผังการทำงานอีกครั้งหากต้องการเก็บไว้

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

git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git checkout <rev>^ -- 
git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git reset HEAD 

(สังเกตช่องว่างท้ายคำสั่งแต่ละคำสั่ง)

ไฟล์ถูกเพิ่มลงในไฟล์ .gitignore แล้วล้างด้วยgit rm. ฉันจำเป็นต้องกู้คืนไฟล์ แต่จากนั้นก็ unstage ไฟล์เหล่านั้น ฉันมีไฟล์หลายร้อยไฟล์ที่จะกู้คืน และการพิมพ์สิ่งต่างๆ ด้วยตนเองสำหรับแต่ละไฟล์ เช่นเดียวกับในตัวอย่างอื่นๆ จะช้าเกินไป

ฉันมีคำถามเดียวกัน ฉันได้สร้างภาระผูกพันโดยไม่รู้ตัว

รายการห้อยต่องแต่งกระทำ

git fsck --lost-found

ตรวจสอบการผูกมัดแต่ละครั้ง

git reset --hard <commit id>

ไฟล์ของฉันปรากฏขึ้นอีกครั้งเมื่อฉันย้ายไปที่การคอมมิทแบบห้อยต่องแต่ง

git status ด้วยเหตุผล:

“HEAD detached from <commit id where it detached>”

ค้นหาคอมมิตที่ลบไฟล์ของคุณ:

git log --diff-filter=D --oneline -- path/to/file | cut -f -d ' '

เอาต์พุตตัวอย่าง:

4711174

ใน Git 2.23 มีrestoreคำสั่งอยู่จริง มันยังคงเป็นรุ่นทดลองแต่เพื่อกู้คืนสิ่งที่คุณลบออกในการคอมมิต (4711174 ในกรณีนี้) คุณสามารถพิมพ์:

git restore --source=4711174^ path/to/file

สังเกต^หลัง id คอมมิต เนื่องจากเราต้องการกู้คืนบางสิ่งจากการคอมมิตก่อนที่จะลบไฟล์

--sourceอาร์กิวเมนต์บอกrestoreคำสั่งที่จะมองหาไฟล์ (s) เพื่อเรียกคืนและมันสามารถใดกระทำและแม้กระทั่งดัชนี

ดู: git-restore doc สำหรับ git 2.23.0

[email protected]:~/work/git$ rm slides.tex
[email protected]:~/work/git$ git pull 
Already up-to-date.
[email protected]:~/work/git$ ls slides.tex
ls: slides.tex: No such file or directory

กู้คืนไฟล์ที่ถูกลบ:

[email protected]:~/work/git$ git checkout
D       .slides.tex.swp
D       slides.tex
[email protected]:~/work/git$ git checkout slides.tex 
[email protected]:~/work/git$ ls slides.tex
slides.tex

หากคุณทราบการคอมมิตที่ลบไฟล์ ให้รันคำสั่งนี้โดยที่คอม<SHA1_deletion>มิตที่ลบไฟล์นั้น:

git diff --diff-filter=D --name-only <SHA1_deletion>~1 <SHA1_deletion> | xargs git checkout <SHA1_deletion>~1 --

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

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

จากคำตอบที่ยอดเยี่ยมของ Charles Bailey นี่คือหนึ่งซับของฉัน:

git co $(git rev-list -n 1 HEAD -- <file_path>)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- <file_path>)~1 head | grep '^D' | cut -f 2)

เรียบง่ายและแม่นยำ-

ก่อนอื่น รับการคอมมิตที่เสถียรล่าสุดที่คุณมีไฟล์นั้นโดย -

git log 

สมมติว่าคุณพบ $commitid 1234567... แล้ว

git checkout <$commitid> $fileName

การดำเนินการนี้จะกู้คืนเวอร์ชันของไฟล์ที่อยู่ในคอมมิตนั้น

ลองใช้วิธีนี้ดูดีที่สุด


ขั้นแรก ให้ค้นหารหัสการคอมมิตของคอมมิตที่ลบไฟล์ของคุณ มันจะให้ข้อมูลสรุปของการคอมมิตซึ่งไฟล์ที่ถูกลบไปให้คุณ

git log --diff-filter=D --summary

git checkout 84sdhfddbdddf~1

หมายเหตุ: 84sdhfddbdddเป็นของคุณcommit id

ด้วยวิธีนี้คุณสามารถกู้คืนไฟล์ที่ถูกลบทั้งหมดได้อย่างง่ายดาย

คุณสามารถคอมgit revertมิตได้เสมอซึ่งลบไฟล์ ( นี่ถือว่าการลบเป็นเพียงการเปลี่ยนแปลงในการคอมมิต )

> git log
commit 2994bda49cd97ce49099953fc3f76f7d3c35d1d3
Author: Dave <[email protected]>
Date:   Thu May 9 11:11:06 2019 -0700

    deleted readme.md

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

> git revert 2994bd

ตอนนี้git logแสดง:

> git log
Author: Dave <[email protected]>
Date:   Thu May 9 11:17:41 2019 -0700

    Revert "deleted readme"

    This reverts commit 2994bda49cd97ce49099953fc3f76f7d3c35d1d3.

และreadme.mdได้รับการกู้คืนในที่เก็บ

จุดบวก:วิธีการด้านล่างใช้ได้ดีกับสถานการณ์ที่ไฟล์/โฟลเดอร์ถูกลบออกจากถังขยะหรือถังรีไซเคิลของคุณ

ไฟล์/โฟลเดอร์จะถูกลบออกจากแผนผังการทำงานแต่ยังไม่ได้คอมมิต:

I. หากคุณยังไม่ได้จัดทำดัชนี (git add) การเปลี่ยนแปลงของคุณ คุณสามารถเปลี่ยนเนื้อหาของไดเรกทอรีกลับได้:

git restore -- path/to/folder_OR_file

ครั้งที่สอง หากการลบได้รับการจัดทำดัชนีแล้ว คุณควรรีเซ็ตสิ่งนั้นก่อน:

git reset -- path/to/folder_OR_file

แล้วดำเนินการ git restore path/to/folder_OR_file

ไฟล์/โฟลเดอร์จะถูกลบในคอมมิตบางรายการในอดีต:

  1. ใช้  git log --diff-filter=D --summary เพื่อรับรายละเอียดของคอมมิตที่ไฟล์/โฟลเดอร์ถูกลบ
  2. ใช้  git checkout $commit~1 path/to/folder_OR_file เพื่อกู้คืนไฟล์/โฟลเดอร์ที่ถูกลบ ที่ไหน  $commit เป็น SHA-ค่าของการกระทำที่คุณได้พบในขั้นตอนที่ 1 เช่น c7578994

หากการลบไม่ถูกคอมมิต คำสั่งด้านล่างจะกู้คืนไฟล์ที่ถูกลบในแผนผังการทำงาน

$ git checkout -- <file>

คุณสามารถรับรายการไฟล์ที่ถูกลบทั้งหมดในแผนผังการทำงานโดยใช้คำสั่งด้านล่าง

$ git ls-files --deleted

หากมีการคอมมิตการลบ ให้ค้นหาการคอมมิตที่เกิดขึ้น จากนั้นกู้คืนไฟล์จากการคอมมิตนี้

$ git rev-list -n 1 HEAD -- <file>
$ git checkout <commit>^ -- <file>

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

$ git log --diff-filter=D --summary

ฉันยังมีปัญหานี้โดยใช้โค้ดด้านล่างเพื่อดึงไฟล์ก่อนหน้าไปยังไดเร็กทอรีในเครื่อง:

git checkout <file path with name>

ตัวอย่างด้านล่างใช้งานได้สำหรับฉัน:

git checkout resources/views/usaSchools.blade.php

คุณสามารถชำระเงินไฟล์ที่ถูกลบ:

git checkout

เอาท์พุต

D       index.html

วิธีคืนค่า:

git restore index.html

หากคุณลบหลายไฟล์และจำเป็นต้องกู้คืนการใช้งานทั้งหมด:

git restore .

ดูภาพ Gif กู้คืนไฟล์โดย git

นี่เป็นวิธีแก้ปัญหาที่ง่ายที่สุดที่ฉันพบหากคุณต้องการกู้คืนไฟล์เดียวกันในไฟล์หลัก:

git checkout master -- path/to/File.java
$ git log --diff-filter=D --summary  | grep "delete" | sort

ในการกู้คืนไฟล์ที่ถูกลบทั้งหมดด้วย Git คุณยังสามารถทำดังนี้

git checkout $(git ls-files --deleted)

โดยgit ls-files --deletedจะแสดงรายการไฟล์ที่ถูกลบทั้งหมดและgit checkout $(git command)กู้คืนรายการไฟล์ในพารามิเตอร์