วิธีการค้นหาไฟล์ที่ถูกลบในโครงการกระทำประวัติ?


1274

กาลครั้งหนึ่งมีไฟล์ในโครงการของฉันที่ตอนนี้ฉันอยากจะได้

ปัญหาคือ: ฉันไม่รู้ว่าเมื่อไหร่ที่ฉันลบมันและเส้นทางที่มันเป็น

ฉันจะหาข้อผูกพันของไฟล์นี้เมื่อมีอยู่ได้อย่างไร?


คำถามที่คล้ายกันที่นี่: stackoverflow.com/questions/7093602/…
eckes

3
มีความเป็นไปได้ที่ซ้ำกันของFind เมื่อไฟล์ถูกลบใน Git
Dan Dascalescu

13
คำตอบที่นี่มีประโยชน์มากขึ้นกว่าที่ฉันคำตอบในที่ซ้ำกัน
เฟลิเป้อัลวาเรซ

5
ตกลง ... โดยไม่คำนึงถึงรายการซ้ำ ... พวกเขาไม่ได้มาในการค้นหาของ Google .... อันนี้ทำ ... ฉันหวังว่าเราจะหยุดการสูญเสียเวลาในการไล่ล่าหลังจากทำซ้ำ ... เวลาเท่านั้นและอัลกอริทึมของ Google จะ บอกได้ว่าคำถามใดดีที่สุด
ทิมโบแลนด์

คำตอบ:


1599

หากคุณไม่ทราบเส้นทางที่แน่นอนคุณสามารถใช้

git log --all --full-history -- "**/thefile.*"

หากคุณรู้เส้นทางของไฟล์คุณสามารถทำได้ดังนี้:

git log --all --full-history -- <path-to-file>

นี่จะแสดงรายการการผูกพันในทุกสาขาที่แตะไฟล์นั้น จากนั้นคุณสามารถค้นหาเวอร์ชันของไฟล์ที่คุณต้องการและแสดงด้วย ...

git show <SHA> -- <path-to-file>

หรือคืนค่าเป็นสำเนาการทำงานของคุณด้วย:

git checkout <SHA>^ -- <path-to-file>

สังเกตสัญลักษณ์คาเร็ต ( ^) ซึ่งได้รับเช็คเอาต์ก่อนที่จะมีการระบุเนื่องจากในขณะ<SHA>ที่ทำการส่งไฟล์ถูกลบเราจำเป็นต้องดูการคอมมิชชันก่อนหน้าเพื่อรับเนื้อหาของไฟล์ที่ถูกลบ


2
ลองใช้เส้นทางสัมพัทธ์แทนเส้นทางสัมบูรณ์ (หากคุณยังไม่ได้เปิด)
แอมเบอร์

63
ถ้าคุณไม่รู้เส้นทางที่แน่นอนล่ะ คุณรู้ชื่อไฟล์ไหม?
นักบวช

17
@PedroMorteRolo git log -- <path>จะไม่มีเอาต์พุตเมื่อคุณอยู่ในสาขาที่ไม่มีไฟล์อยู่ คุณควรใช้git log --all -- <path>เพื่อให้แน่ใจว่าคุณจะไม่พลาดการเปลี่ยนแปลงที่เกิดขึ้นในสาขาอื่น คำสั่งgit log -- <path>อาจเป็นอันตรายได้หากคุณมีสาขามากกว่าหนึ่งสาขาและมีแนวโน้มที่จะลืมเส้นทางและสาขา (เช่นฉัน) และมันก็อันตรายเช่นกันหากคุณทำงานกับผู้พัฒนารายอื่น
เตาแก๊ส

4
@Amber ให้ลองเพิ่ม--all(ขอบคุณPhilip ) ในgit logคำตอบของคุณเพื่อให้คนไม่พลาดการเปลี่ยนแปลงและไฟล์ในสาขาอื่น มันจะช่วยคนที่หลงลืมเช่นเดียวกับฉันความเศร้าโศกมากมาย
เตาแก๊ส

3
ดังที่ระบุไว้ในคำตอบด้านล่างการกู้คืนไฟล์ควรเป็นgit checkout <SHA>^ -- <path-to-file>(หมายเหตุสัญลักษณ์ ^) เนื่องจากในขณะที่ <SHA> ส่งไฟล์ถูกลบเราจำเป็นต้องดูการคอมมิชชันก่อนหน้าเพื่อรับเนื้อหาของไฟล์ที่ถูกลบ
kipelovets

393

รับรายการไฟล์ที่ถูกลบและคัดลอกพา ธ เต็มของไฟล์ที่ถูกลบ

git log --diff-filter=D --summary | grep delete

ดำเนินการคำสั่งถัดไปเพื่อค้นหากระทำ id ของการกระทำที่และคัดลอกกระทำรหัส

git log --all -- FILEPATH

แสดงส่วนต่างของไฟล์ที่ถูกลบ

git show COMMIT_ID -- FILE_PATH

จำไว้ว่าคุณสามารถเขียนผลลัพธ์ไปยังไฟล์โดยใช้>ไลค์

git show COMMIT_ID -- FILE_PATH > deleted.diff

1
unknown revision or path not in the working treeถึงแม้ว่าผมจะพบเส้นทางด้วยความช่วยเหลือของขั้นตอนแรกขั้นตอนที่สองโยนข้อผิดพลาดนี้:
jvannistelrooy

6
หากต้องการดูแฮชการกระทำพร้อมกับการลบคุณสามารถทำได้git log --diff-filter=D --summary | grep -E 'delete|^commit\s+\S+'
Chris Middleton

1
ขั้นตอนที่ 2 ไม่ส่งคืนอะไร ความคิดใด ๆ ว่าทำไมมันอาจเกิดขึ้น? ชื่อไฟล์ของฉันถูกต้อง
Denis Kniazhev

2
ในการค้นหารวมทั้งสามเข้าด้วยกันให้เพิ่มนี่ลงใน. bashrc หรือ. zshrc ของคุณ: git-grep-latest(){ result_path=$(git log --diff-filter=D --summary | grep $1 | head -1 | awk '{print $4;}'); latest_commit=$(git log --all -- $result_path | head -1 | awk '{print $2;}'); git show $latest_commit -- $result_path; }และตอนนี้คุณสามารถทำได้:git-grep-latest some_text
randomor

1
@TylerJones คุณสามารถให้อาหารอะไรก็ได้กับ linux โดยใช้ pipes - google linux pipes.. คุณจะชอบแบบนั้น
John Hunt

37

ไม่สามารถแก้ไขคำตอบที่ยอมรับเพื่อเพิ่มเป็นคำตอบที่นี่

เพื่อกู้คืนไฟล์ในคอมไพล์ใช้ต่อไปนี้ (สังเกตเครื่องหมาย '^' หลังจาก SHA)

git checkout <SHA>^ -- /path/to/file

ฉันไม่เข้าใจว่าทำไมคุณต้องการ ^ ไฟล์อยู่ในการกระทำที่มี SHA นั้น ... ทำไมคุณต้องการที่จะเดินกลับการกระทำอื่นจากที่นั่น?
Tony K.

19
มันอยู่ในความมุ่งมั่นกับ sha ว่า "ลบ" ซึ่งหมายความว่ามันยังคงไม่มีอยู่ คุณต้องไปกระทำก่อนหน้านั้นเพื่อรับมันกลับคืนมา
tandrewnichols

6
@trewrewnichols ซึ่งหมายความว่าคุณกำลังใช้ SHA ที่ไม่ถูกต้อง - คุณต้องการคอมมิทสำหรับเวอร์ชันของไฟล์ที่คุณต้องการ ... ซึ่งอาจไม่ใช่เวอร์ชันที่ไฟล์ถูกลบ
เหลืองอำพัน

6
@Amber และความมุ่งมั่นที่คุณต้องการนั้นน่าจะเป็นสิ่งล่าสุดก่อนที่จะถูกลบไปดังนั้นคำตอบนี้
Sam Holder

1
@AlexR: <SHA>~1ควรทำงานเหมือนเดิมโดยไม่จำเป็นต้องห่อด้วยเครื่องหมายคำพูด
CodeManX

37

สมมติว่าคุณต้องการกู้คืนไฟล์ที่เรียกว่าMyFileแต่ไม่แน่ใจในพา ธ (หรือส่วนขยายของไฟล์สำหรับเรื่องนั้น):

คำนำ: หลีกเลี่ยงความสับสนด้วยการก้าวไปที่รากคอมไพล์

โครงการที่ไม่สำคัญอาจมีหลายไดเรกทอรีที่มีชื่อคล้ายหรือเหมือนกัน

> cd <project-root>
  1. ค้นหาเส้นทางแบบเต็ม

    บันทึก git --diff-filter = D - สรุป | grep ลบ grep MyFile

    delete mode 100644 full/path/to/MyFile.js

full/path/to/MyFile.js คือเส้นทางและไฟล์ที่คุณกำลังค้นหา

  1. พิจารณาการกระทำทั้งหมดที่มีผลกับไฟล์นั้น

    บันทึก git - ออนไลน์ - ติดตาม - เต็ม / เส้นทาง / ถึง / MyFile.js

    bd8374c Some helpful commit message

    ba8d20e Another prior commit message affecting that file

    cfea812 The first message for a commit in which that file appeared.

  2. ชำระเงินไฟล์

หากคุณเลือกคอมมิชชันรายการแรก (ลำดับสุดท้ายที่นี่ bd8374c) จะไม่พบไฟล์เนื่องจากถูกลบในคอมมิชชันนั้น

> git checkout bd8374c -- full/path/to/MyFile.js

`error: pathspec 'full/path/to/MyFile.js' did not match any file(s) known to git.`

เพียงเลือกก่อนหน้า (ผนวกเครื่องหมายรูปหมวก) กระทำ:

> git checkout bd8374c^ -- full/path/to/MyFile.js

3
นี่เป็นคำตอบที่ชัดเจนกว่ามาก
Pouyan Khodabakhsh

สำหรับ windows console (cmd) ให้ใช้ find แทน grep ในขั้นตอนที่ 2: git log --diff-filter=D --summary | find "delete" | find "MyFile"และ step3 ให้สังเกตเครื่องหมายคำพูดรอบ ๆ แฮช:git checkout "bd8374c^" -- full/path/to/MyFile.js
user5542121

30

@Amber ให้คำตอบที่ถูกต้อง! นอกจากนี้อีกหนึ่งถ้าคุณไม่ทราบเส้นทางที่แน่นอนของไฟล์คุณสามารถใช้อักขระตัวแทน! สิ่งนี้ใช้ได้สำหรับฉัน

git log --all -- **/thefile.*

4
@PedroMorteRolo อืม ฉันไม่รู้ว่าฉันรู้สึกอย่างไรเกี่ยวกับการคัดลอกคำตอบที่มีอยู่ไปยังคำตอบที่โหวตแล้ว: / คำตอบนี้มีประโยชน์เช่นกัน; การโหวตอาจจะเพียงพอหรือไม่
Clément

1
ไม่พบไฟล์หากอยู่ในรูทโปรเจ็กต์ (ทดสอบใน Cygwin)
wortwart

19

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

git log --diff-filter=D --summary | grep filename | awk '{print $4; exit}' | xargs git log --all -- 

หากใครสามารถปรับปรุงคำสั่งโปรดทำ


1
เยี่ยมมากขอบคุณ! ดูเหมือนไฟล์ของฉันไม่เคยมีอยู่เลย แต่นั่นเป็นปัญหาที่แยกออกมาและมีขนดกมาก…

ตรวจสอบให้แน่ใจว่าคุณเรียกใช้จากไดเรกทอรีรากของที่เก็บหากไฟล์ของคุณดูเหมือนว่า 'ขาด'
samaspin

ขอบคุณ @ Samaspin อัปเดตคำตอบ
Jason

18

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


4
ว่า--allเป็นตัวเลือกที่สำคัญสำหรับทั้งคำตอบและคำตอบที่ได้รับการยอมรับของคุณ
เตาแก๊ส

3
การดูประวัติจะใช้เวลาไม่มากสำหรับโครงการส่วนใหญ่
mikemaccana

5

สรุป:

  1. ขั้นตอนที่ 1

คุณค้นหาเส้นทางแบบเต็มไฟล์ในประวัติของไฟล์ที่ถูกลบ git log --diff-filter=D --summary | grep filename

  1. ขั้นตอนที่ 2

คุณกู้คืนไฟล์ของคุณจากการกระทำก่อนที่จะถูกลบ

restore () {
  filepath="$@"
  last_commit=$(git log --all --full-history -- $filepath | grep commit | head -1 | awk '{print $2; exit}')
  echo "Restoring file from commit before $last_commit"
  git checkout $last_commit^ -- $filepath
}

restore my/file_path

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