Git'te bir dosyanın ne zaman silindiğini bulma


1035

N işlemeli bir Git depom var.

İhtiyacım olan bir dosyam var ve bu eskiden depodaydı ve aniden "Ah! Bu dosya nereye gitti?"

Git "komutları n-13'te gerçekten_needed.txt dosyasının silindiğini" söyleyecek bir (dizi) Git komutu var mı?

Diğer bir deyişle, her bireysel işleme bakmadan ve Git depomun her dosyada her değişikliğe sahip olduğunu bilmeden, bu dosyanın HAS olan son taahhüdü hızlı bir şekilde bulabilir miyim, böylece geri alabilir miyim?



2
Pedro tarafından paylaşılan bağlantı sorumun cevabına sahipti: yolu hatırlamadığınızda silinmiş bir dosyayı nasıl bulabilirim.
Gordon Bean

Yanıtlar:


1127

git log --full-history -- [file path] dosyadaki değişiklikleri gösterir, dosya silinmiş olsa bile çalışın.

Misal:

git log --full-history  -- myfile

Yalnızca bir dosyayı silen son taahhüdü görmek istiyorsanız, ek olarak -1 kullanın, örn. git log --full-history -1 -- [file path]

Hangi işlemin bir dosyayı sildiğine bakın


16
kalıp aramak mümkün mü? Dosyanın tam adını unuttum = (belki de tüm silme işlemlerinin bir kaydını almak mümkün mü?
wutzebaer


6
PowerShell kullanıyorsanız, tire işaretlerinden kaçılması gerektiğini lütfen unutmayın: git log '-' [dosya yolu]. Umarım bu başka birileri diş yırtıcı olabilir.
A. Wilson

68
git log -- */<<filename>>.<<file extension>>Tüm dosya yolunu bilmeden arama yapabildim .
Tom Howard

2
@Devamlı köşeli parantezler gerçek dosya yolu için bir yer tutucu olarak bulunur.
Emile Bergeron

229

Kısa cevap:

git log --full-history -- your_file

repo tarihinizdeki, birleştirilen birleştirme taahhütleri de dahil olmak üzere tüm taahhütleri gösterecektir your_file. Sonuncusu (üstte) dosyayı silen dosyadır.

Bazı açıklamalar:

Buradaki --full-historybayrak önemlidir. Bu olmadan Git, bir dosyanın günlüğünü istediğinde "geçmiş sadeleştirmesi" gerçekleştirir. Dokümanlar tam olarak bunun nasıl çalıştığı hakkında ayrıntılara ışık tutuyor ve kaynak koddan anlamaya çalışmak için gerekli olan cesaret ve cesaretten yoksun, ama git-log dokümanlar söyleyecek çok şey var:

Varsayılan mod

Tarihi, ağacın son durumunu açıklayan en basit tarihe sadeleştirir. En basittir, çünkü sonuç sonucu aynıysa bazı yan dalları budanır (yani aynı içeriğe sahip dalları birleştirmek)

Açıkçası, geçmişini istediğimiz dosyanın silinmesi ile ilgilidir , çünkü silinen bir dosyanın son durumunu açıklayan en basit tarih geçmiş değildir . git logOlmadan --full-historysadece dosyanın asla oluşturulmadığını iddia etme riski var mı ? Maalesef evet. İşte bir gösteri:

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 -- barYukarıdaki terminal dökümünde kelimenin tam anlamıyla nasıl çıkış olmadığına dikkat edin ; Git tarihi barhiç olmadığı bir kurguya "sadeleştiriyor" . git log --full-history -- bardiğer taraftan, bize yaratan taahhüdü ve silen taahhüdü verir bar.

Açık olmak gerekirse: bu konu sadece teorik değildir. Yalnızca dokümanlara baktım ve --full-historybayrağı keşfettim çünkü git log -- some_filesilinen bir dosyayı izlemeye çalıştığım gerçek bir depoda başarısız oluyordu. Mevcut bir dosyanın mevcut durumunda nasıl olduğunu anlamaya çalıştığınızda, geçmişin basitleştirilmesi bazen yararlı olabilir , ancak bir dosya silme işlemini izlemeye çalışırken, önem verdiğiniz taahhüdü gizleyerek sizi mahvetme olasılığı daha yüksektir . --full-historyBu kullanım durumu için her zaman bayrağı kullanın.


4
Bunun yalnızca geçerli dalla ilgili geçmişi aradığını unutmayın ('tam repo geçmişi' ile değil) ... yani, dosya geçerli dalda henüz silinmemiş ancak başka bir dalda bulunmuşsa, silme işlemini bulamazsınız. Dosyanın zaten silinmiş olduğu herhangi bir dalda olmanız gerekir . Bunu düşünürken belki açıktır, ama ilk başta beni yakaladı.
2018

1
Bu cevap işe yarıyor. Ancak git logçıktının kendisinden, son taahhüdün dosyayı sildiği hiç de belli değil . Ben de denedim git log --name-status --full-history -- file_nameve git log -p --stat --full-history -- file_name, ama ne açıkça son dosyanın kaldırıldığını gösterir. Bu bir hata gibi görünüyor.
Martin_W

@Martin_ATS ve benim için Git 2.12.2 ile günlük çıktısını 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 -- bariçerir . Çıktıda bu satırları görmüyor musunuz? Hangi versiyona sahipsin? D barA bar
Mark Amery

git version 2.15.1Evet, komut diziniz D barve A bar. Belki de benim sorunum dosyamın geçmişine özgüdür. .htaccessGitignore'ed ve kaldırılan bir dosyanın geçmişini izliyordum. Sonunda bunu anladım ve dosyayı geri ekledim. Ben eklediğinizde --name-statusiçinde git logkomuta, iki bkz A .htaccess(ekledim çünkü işlemek son arkaya) ama hiçbir girdileri D .htaccess. Bu nedenle, bazı durumlarda bir dosya depodan kaldırılmış olsa bile, git logaçık bir D file_namegiriş gösterilmeyecektir.
Martin_W

@Martin_ATS Meraklı. Acaba .htaccessX'in bir X taahhüdüne eklendiği, ancak X'i master'a getiren birleştirme taahhüdüne dahil edilip edilmediğini merak ediyorum ? Bir dosya eklenmiş ve hiç silinmemiş ve hala mevcut olmayan bir dosya gibi görünmesi gerektiğini iddia edebileceğim tek şey bu. Bir MCVE'yi anlamaya çalışmak ilginç olur, sonra bunun bir Git hatası olup olmadığını ve eğer değilse, davanızı ele almak için cevabımı değiştirmenin mümkün olup olmadığını anlayın.
Mark Amery

84

Git günlüğü ancak yolun önüne --

Örneğin:

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

Ben burada bir çözüm ekledim (git içinde depodaki tüm silinmiş dosyaları listelemek için bir yolu var mı?) Bir regexp kullanarak silinen dosyaların taahhütlerini bulmak için:

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

Bu, some_dir(basamaklı) adlı bir dizinde silinen her şeyi döndürür . Orada herhangi bir sed regexp \/some_dir\/yapacak.

OSX (@triplee ve @keif sayesinde)

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

1
Güzel. OS X'te bash altında bazı uyumsuzluklar:sed: 1: "/^commit/h;/\/some_dir\ ...": bad flag in substitute command: '}'
Brent Faust

@BrentFoust Bunu test edemediğim bir pitty ... sonunda bir boşluk eklemeyi deneyin (parantezden sonra ama tek alıntıdan önce), çevrimiçi man sayfası bu konuda net değil ...
estani

Güzel öneri. Ancak tek alıntıdan önce bir boşluk eklemek yardımcı olmadı. Kapanış ayracı öncesinde de boşluk yoktu.
Brent Faust

1
BSD / OSX sedgörünüşe göre komut ayırıcılar olarak noktalı virgüllerle her zaman iyi değildir. Bunları yeni satırlara değiştirmeyi deneyin veya şu konuma geçinsed -n -e '/^commit/h' -e '\:/some_dir/:{' -e G -e 's/\ncommit \(.*\)/ \1/gp' -e }
tripleee

1
Test ettim ve git log --diff-filter=D --summary | sed -n -e '/^commit/h' -e '\:/:{' -e G -e 's/\ncommit \(.*\)/ \1/gp' -e }benim için OSX'te çalıştım.
keif

21

Silinen son taahhüdü şu şekilde bulabilirsiniz:

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

Daha fazla bilgiyi burada bulabilirsiniz


11
Birincil iyileştirilmiş çözüm benim için işe yaramadı, ama bu işe yaradı.
Nick Heiner

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.