ค้นหาเมื่อไฟล์ถูกลบใน Git


1035

ฉันมีที่เก็บ Git พร้อม n คอมมิต

ฉันมีไฟล์ที่ฉันต้องการและเคยอยู่ในที่เก็บและฉันก็มองหาและคิดว่า "โอ้ไฟล์นั้นหายไปไหน?"

มีคำสั่ง Git (ชุด) ที่จะบอกฉันว่า "ไฟล์ really_needed.txt ถูกลบตอนคอมมิท n-13" หรือไม่?

กล่าวอีกนัยหนึ่งโดยไม่ต้องดูที่การกระทำของแต่ละคนและรู้ว่า repo Git ของฉันมีการเปลี่ยนแปลงทุกไฟล์ฉันสามารถหาการกระทำสุดท้ายที่ HAS นั้นเป็นไฟล์นั้นได้อย่างรวดเร็วดังนั้นฉันจะเอามันกลับมาได้หรือไม่



2
ลิงก์ที่แชร์โดย Pedro มีคำตอบให้กับคำถามของฉัน: วิธีค้นหาไฟล์ที่ถูกลบเมื่อคุณจำเส้นทางไม่ได้
Gordon Bean

คำตอบ:


1127

git log --full-history -- [file path] แสดงการเปลี่ยนแปลงของไฟล์ทำงานแม้ว่าไฟล์จะถูกลบ

ตัวอย่าง:

git log --full-history  -- myfile

หากคุณต้องการเห็นเฉพาะการส่งครั้งล่าสุดซึ่งลบไฟล์ใช้ -1 นอกจากนี้เช่น git log --full-history -1 -- [file path]

ดูไฟล์ที่ลบคอมมิต


16
เป็นไปได้ไหมที่จะค้นหารูปแบบ? ฉันลืมชื่อเต็มของไฟล์ = (อาจเป็นไปได้ที่จะได้รับบันทึกการลบทั้งหมดหรือไม่?
wutzebaer

6
พบได้ที่นี่: stackoverflow.com/questions/6017987/…
wutzebaer

6
โปรดทราบว่าหากคุณใช้ PowerShell ยัติภังค์จะต้องถูกหลบหนี: git log '-' [เส้นทางไฟล์] หวังว่านี่จะเหมือนกันกับบางคนที่กัดฟัน
A. วิลสัน

68
ฉันสามารถค้นหาโดยใช้ที่git log -- */<<filename>>.<<file extension>>ไม่รู้จักเส้นทางไฟล์ทั้งหมด
Tom Howard

2
@MERose วงเล็บเหลี่ยมจะมีเป็นตัวยึดตำแหน่งสำหรับเส้นทางของไฟล์จริง
Emile Bergeron

229

คำตอบสั้น ๆ :

git log --full-history -- your_file

จะแสดงให้คุณทุกกระทำในประวัติศาสตร์ repo your_fileของคุณรวมทั้งกระทำผสานที่สัมผัส อันสุดท้าย (บนสุด) คืออันที่ลบไฟล์

คำอธิบายบางอย่าง:

--full-historyธงนี่เป็นสิ่งสำคัญ ถ้าไม่มีมัน Git จะทำ "การทำให้เข้าใจง่ายประวัติศาสตร์" เมื่อคุณถามถึงบันทึกของไฟล์ เอกสารมีรายละเอียดที่ชัดเจนเกี่ยวกับวิธีการทำงานและฉันขาดความพยายามและความกล้าหาญที่จะพยายามหามันออกมาจากซอร์สโค้ด แต่เอกสาร git-logนั้นมีสิ่งต่าง ๆ มากมายที่จะกล่าวถึง:

โหมดเริ่มต้น

ลดความซับซ้อนของประวัติศาสตร์ให้เป็นประวัติที่ง่ายที่สุดที่อธิบายสถานะสุดท้ายของต้นไม้ ง่ายที่สุดเพราะมันตัดกิ่งไม้ด้านข้างบางส่วนถ้าผลลัพธ์สุดท้ายเหมือนกัน (เช่นการรวมกิ่งไม้กับเนื้อหาเดียวกัน)

นี้จะเห็นได้ชัดเกี่ยวกับเมื่อแฟ้มที่มีประวัติที่เราต้องการจะลบตั้งแต่ประวัติศาสตร์ที่ง่ายที่สุดในการอธิบายรัฐสุดท้ายของไฟล์ที่ถูกลบคือไม่มีประวัติ มีความเสี่ยงหรือgit logไม่ที่--full-historyจะอ้างว่าไฟล์นั้นไม่เคยถูกสร้างขึ้นมาหรือไม่? น่าเสียดายใช่ นี่คือการสาธิต:

mark@lunchbox:~/example$ git init
Initialised empty Git repository in /home/mark/example/.git/
mark@lunchbox:~/example$ touch foo && git add foo && git commit -m "Added foo"
[master (root-commit) ddff7a7] Added foo
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 foo
mark@lunchbox:~/example$ git checkout -b newbranch
Switched to a new branch 'newbranch'
mark@lunchbox:~/example$ touch bar && git add bar && git commit -m "Added bar"
[newbranch 7f9299a] Added bar
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 bar
mark@lunchbox:~/example$ git checkout master
Switched to branch 'master'
mark@lunchbox:~/example$ git rm foo && git commit -m "Deleted foo"
rm 'foo'
[master 7740344] Deleted foo
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 foo
mark@lunchbox:~/example$ git checkout newbranch
Switched to branch 'newbranch'
mark@lunchbox:~/example$ git rm bar && git commit -m "Deleted bar"
rm 'bar'
[newbranch 873ed35] Deleted bar
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 bar
mark@lunchbox:~/example$ git checkout master
Switched to branch 'master'
mark@lunchbox:~/example$ git merge newbranch
Already up-to-date!
Merge made by the 'recursive' strategy.
mark@lunchbox:~/example$ git log -- foo
commit 77403443a13a93073289f95a782307b1ebc21162
Author: Mark Amery 
Date:   Tue Jan 12 22:50:50 2016 +0000

    Deleted foo

commit ddff7a78068aefb7a4d19c82e718099cf57be694
Author: Mark Amery 
Date:   Tue Jan 12 22:50:19 2016 +0000

    Added foo
mark@lunchbox:~/example$ git log -- bar
mark@lunchbox:~/example$ git log --full-history -- foo
commit 2463e56a21e8ee529a59b63f2c6fcc9914a2b37c
Merge: 7740344 873ed35
Author: Mark Amery 
Date:   Tue Jan 12 22:51:36 2016 +0000

    Merge branch 'newbranch'

commit 77403443a13a93073289f95a782307b1ebc21162
Author: Mark Amery 
Date:   Tue Jan 12 22:50:50 2016 +0000

    Deleted foo

commit ddff7a78068aefb7a4d19c82e718099cf57be694
Author: Mark Amery 
Date:   Tue Jan 12 22:50:19 2016 +0000

    Added foo
mark@lunchbox:~/example$ git log --full-history -- bar
commit 873ed352c5e0f296b26d1582b3b0b2d99e40d37c
Author: Mark Amery 
Date:   Tue Jan 12 22:51:29 2016 +0000

    Deleted bar

commit 7f9299a80cc9114bf9f415e1e9a849f5d02f94ec
Author: Mark Amery 
Date:   Tue Jan 12 22:50:38 2016 +0000

    Added bar

โปรดสังเกตว่าgit log -- barเทอร์มินัลดัมพ์ด้านบนส่งผลให้ไม่มีเอาต์พุตอย่างแท้จริง Git คือ "ลดความซับซ้อน" ประวัติศาสตร์ลงในนิยายที่barไม่เคยมีอยู่ git log --full-history -- barในทางกลับกันทำให้เรามีความมุ่งมั่นที่สร้างขึ้นbarและความมุ่งมั่นที่จะลบมัน

มีความชัดเจน: ปัญหานี้ไม่เพียง แต่ในทางทฤษฎี ฉันดูเอกสารเท่านั้นและค้นพบการ--full-historyตั้งค่าสถานะเนื่องจากgit log -- some_fileความล้มเหลวสำหรับฉันในที่เก็บข้อมูลจริงที่ฉันพยายามติดตามไฟล์ที่ถูกลบ การทำให้เข้าใจประวัติบางครั้งอาจมีประโยชน์เมื่อคุณพยายามที่จะเข้าใจว่าไฟล์ที่มีอยู่ในปัจจุบันมาเป็นอย่างไรในปัจจุบัน แต่เมื่อพยายามติดตามการลบไฟล์มันมีแนวโน้มที่จะทำให้คุณสับสนโดยการซ่อนความมุ่งมั่นที่คุณใส่ใจ . ใช้--full-historyแฟล็กสำหรับกรณีการใช้งานนี้เสมอ


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

1
คำตอบนี้ใช้ได้ผล แต่จากgit logผลลัพธ์เองมันไม่ได้ชัดเจนเลยว่าการส่งครั้งล่าสุดลบไฟล์ไปแล้ว ฉันยังพยายามgit log --name-status --full-history -- file_nameและgit log -p --stat --full-history -- file_nameแต่ไม่ชัดเจนแสดงว่าไฟล์ถูกลบออกในรุ่นล่าสุดกระทำ ดูเหมือนว่าจะเป็นข้อผิดพลาด
Martin_W

@Martin_ATS mkdir somedir && cd somedir && git init && touch foo && git add foo && git commit -m "Added foo" && git checkout -b newbranch && touch bar && git add bar && git commit -m "Added bar" && git checkout master && git rm foo && git commit -m "Deleted foo" && git checkout newbranch && git rm bar && git commit -m "Deleted bar" && git checkout master && git merge newbranch && git log --name-status --full-history -- barรวมD barและA barสำหรับฉันในบันทึกผลลัพธ์ด้วย Git 2.12.2 คุณไม่เห็นบรรทัดเหล่านั้นในผลลัพธ์หรือไม่ คุณมีรุ่นอะไร
Mark Amery

git version 2.15.1ใช่ลำดับคำสั่งของคุณไม่รายงานและD bar A barบางทีปัญหาของฉันอาจเป็นประวัติของไฟล์ของฉัน ฉันกำลังติดตามประวัติของ.htaccessไฟล์ที่ได้รับ gitignore'ed และลบออก ในที่สุดฉันก็ค้นพบมันและเพิ่มไฟล์กลับมา เมื่อฉันรวม--name-statusอยู่ในgit logคำสั่งผมเห็นสองA .htaccessรายการ (ตั้งแต่ฉันเพิ่มมันกลับล่าสุดกระทำ) D .htaccessแต่ไม่มี ดังนั้นจึงดูเหมือนในบางกรณีแม้ว่าไฟล์ถูกลบออกจากพื้นที่เก็บข้อมูลgit logจะไม่แสดงD file_nameรายการที่ชัดเจน
Martin_W

@Martin_ATS อยากรู้อยากเห็น ฉันสงสัยว่าบางทีการ.htaccessเพิ่มเข้ามาใน commit X แต่ไม่รวมอยู่ในการคอมมิชชันที่ทำให้ X เข้าสู่การเป็นมาสเตอร์? นั่นเป็นสิ่งเดียวที่ฉันคิดได้ว่าฉันอาจโต้เถียงได้ว่าควรมีลักษณะเหมือนไฟล์ที่ถูกเพิ่มและไม่เคยถูกลบ แต่ก็ยังไม่ปรากฏ คงเป็นเรื่องที่น่าสนใจที่จะลองใช้ MCVE และลองคิดดูว่ามันเป็น Git bug หรือไม่และถ้าเป็นไปได้ที่จะปรับแต่งคำตอบเพื่อจัดการกับกรณีของคุณ
Mark Amery

84

บันทึก Git แต่คุณต้องนำหน้าเส้นทางด้วย --

เช่น:

dan-mac:test dani$ git log file1.txt
fatal: ambiguous argument 'file1.txt': unknown revision or path not in the working tree.

dan-mac:test dani$ git log -- file1.txt
 commit 0f7c4e1c36e0b39225d10b26f3dea40ad128b976
 Author: Daniel Palacio <danpal@gmail.com>
 Date:   Tue Jul 26 23:32:20 2011 -0500

 foo

31

ฉันเพิ่งเพิ่มโซลูชันที่นี่(มีวิธีในคอมไพล์รายการไฟล์ที่ถูกลบทั้งหมดในพื้นที่เก็บข้อมูลหรือไม่)สำหรับการค้นหากระทำของไฟล์ที่ถูกลบโดยใช้ regexp:

git log --diff-filter=D --summary | sed -n '/^commit/h;/\/some_dir\//{G;s/\ncommit \(.*\)/ \1/gp}'

สิ่งนี้จะคืนค่าทุกสิ่งที่ถูกลบภายในไดเรกทอรีที่ชื่อsome_dir(เรียงซ้อน) ผู้ที่\/some_dir\/มีประสบการณ์จะทำอะไร

OSX (ขอบคุณ @triplee และ @keif)

git log --diff-filter=D --summary | sed -n -e '/^commit/h' -e '\:/:{' -e G -e 's/\ncommit \(.*\)/ \1/gp' -e }

1
ดี ความไม่ตรงกันบางอย่างภายใต้การทุบตีใน OS X:sed: 1: "/^commit/h;/\/some_dir\ ...": bad flag in substitute command: '}'
Brent Faust

@BrentFoust มัน pitty ฉันไม่สามารถทดสอบว่า ... ลองเพิ่มช่องว่างที่ท้าย (หลังจากการจัดฟัน แต่ก่อนที่จะพูดเดียว) หน้าคนออนไลน์ไม่ชัดเจนเกี่ยวกับที่ ...
estani

คำแนะนำที่ดี แต่การเพิ่มช่องว่างก่อนที่คำพูดเดียวจะไม่ช่วย ไม่มีช่องว่างก่อนวงเล็บปีกกาปิด
Brent Faust

1
BSD / OSX sedไม่ได้ดีเสมอกับอัฒภาคในฐานะตัวคั่นคำสั่ง ลองเปลี่ยนเป็นบรรทัดใหม่หรือเปลี่ยนเป็นsed -n -e '/^commit/h' -e '\:/some_dir/:{' -e G -e 's/\ncommit \(.*\)/ \1/gp' -e }
tripleee

1
ฉันทดสอบและgit log --diff-filter=D --summary | sed -n -e '/^commit/h' -e '\:/:{' -e G -e 's/\ncommit \(.*\)/ \1/gp' -e }ทำงานให้ฉันใน OSX
keif

21

คุณสามารถค้นหาการคอมมิทล่าสุดที่ลบไฟล์ดังต่อไปนี้:

git rev-list -n 1 HEAD -- [file_path]

ข้อมูลเพิ่มเติมสามารถดูได้ที่นี่


11
โซลูชัน upvoted หลักไม่ทำงานสำหรับฉัน แต่อันนี้ทำ
Nick Heiner

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