Soru Git deposunda silinmiş bir dosyayı bulup geri yükleme


Git deposunda olduğumu söyle. Bir dosyayı sildim ve bu değişikliği yapıyorum. Çalışmaya devam ediyorum ve daha fazla taahhütte bulunuyorum. Sonra, bu dosyayı geri yüklemem gerektiğini anladım.

Kullanarak bir dosyayı kontrol edebileceğimi biliyorum. git checkout HEAD^ foo.barama bu dosyanın ne zaman silindiğini bilmiyorum.

  1. Belirli bir dosya adını silme işlemini bulmak için en hızlı yol ne olurdu?
  2. Bu dosyayı çalışma kopyasına geri yollamanın en kolay yolu ne olurdu?

Günlüklerime manuel olarak göz atmam, belirli bir SHA için tüm projeyi kontrol etmem ve daha sonra bu dosyayı orijinal proje kontrolüne el ile kopyalamam gerekmiyor.


2386
2018-06-04 22:40


Menşei


$ git checkout deletedFileHiç kimse bunu açıkça belirtmedi mi ?! Gelecekteki Google çalışanları için başlığa cevap verin ... - hhh
Bir önceki yorumun soruyu soruda başlıkta değil, bedende değil - bulmayı da içerdiğini unutmayın. ne zaman dosya silindi. - avdgaag
Bir dosyada bulunan işlemi bulmak için: git log --diff-filter=D -- path/to/file - titaniumdecoy
İlgili: Git'teki değişmemiş değişiklikleri nasıl atıyorsunuz?.
@hhh git checkout deletedFile geri çekilecek deletedFile silinmişse silinmişse henüz sahnelenmemiş veya işlenmemiş. Burada sorulan soru bu değil; Bu soru, silme işleminin daha önce birçok taahhütte bulunduğu bir dosyanın nasıl geri yükleneceği ile ilgilidir. - Mark Amery


Cevaplar:


Verilen yolu etkileyen son işlemi bulun. Dosya HEAD taahhüdünde olmadığından, bu işlemin silinmiş olması gerekir.

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

Daha sonra, taktiyi kullanarak, daha önce taahhütte bulunan versiyonu kontrol edin.^) sembolü:

git checkout <deleting_commit>^ -- <file_path>

Ya da tek bir komutta $file söz konusu dosyadır.

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

Zsh kullanıyorsanız ve EXTENDED_GLOB seçeneğinin etkinleştirilmiş olması durumunda, düzeltme işareti simgesi çalışmaz. Kullanabilirsiniz ~1 yerine.

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

2725
2017-07-11 07:12



Zor olan bit, ^ sonek kullanılarak ÖNCE taahhüdünü kontrol etmektir. Teşekkürler. - Christian Oudard
Sonunda ^ ne için? - ranman
@Ranman: "İlk ebeveyn" anlamına gelir. - CB Bailey
Windows komut satırından bir hata aldım. error: pathspec <filename> did not match any file(s) known to git.. Çözüm git bash kullanmaktı. - donturner
@zoras zsh in '^' üzerinde kendi açılımı var, ama '~ 1' alternatif sözdizimini kullanabilirsiniz: git checkout <deleting-commit>~1 -- <file-path>  ~ X, belirtilen taahhütten önce X taahhütlerini belirtmenize izin verir, bu yüzden ~ 1 önce taahhüt, ~ 2 önce iki taahhüt, vb. - Nils Luxton


  1. kullanım git log --diff-filter=D --summary Silinen dosyaları ve dosyaları silinen tüm taahhütleri almak için;
  2. kullanım git checkout $commit~1 filename silinen dosyayı geri yüklemek için

Nerede $commit 1. adımda bulduğunuz taahhütün değeri, ör. e4cf499627


724
2018-06-04 23:10



meraklı, ~ 1 ne ifade eder? - tommy chheng
@tommy - tilde spec size adlandırılmış taahhüdün nth torunu verecektir. Görmek book.git-scm.com/4_git_treeishes.html daha fazla ayrıntı için . - Robert Munteanu
Bu, en kolay ve sezgisel yaklaşımdır. git log -- *PartOfMyFileName*. İçin teşekkürler $commit~1 - bgs
git checkout $commit~1 filename sözdizimi, tek tek dosyalar için mükemmel çalışır ve ayrıca tüm dizinler için çalışır. Örn:: ./images içindeki tüm silinmiş görüntüleri sha 12345'den geri yüklemek için: git checkout 12345~1 images. bu cevap için teşekkürler! - noinput
@Alexar $commit~1 işlemin adını eklemeniz gerektiği anlamına gelir. Gibi bir şey 1d0c9ef6eb4e39488490543570c31c2ff594426c nerede $commit olduğunu. - Eugene


Bir klasördeki tüm silinmiş dosyaları geri yüklemek için aşağıdaki komutu girin.

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

302
2017-12-02 06:11



Dosyalar nereye taşınır? Hiçbir değişiklik görmüyorum. - William Grand
Bu muhtemelen en kolay yöntemdir. Onun sapkın ne kadar zor git En basit görevi bile yaptı. - jww
ne demek -- ? - Tebe
git checkout - [dosya], [dosya] 'daki değişiklikleri geri alır. Boru, silinmiş dosyaların adıyla [dosya] yerini alacaktır. - Manu
ls-files alt komut kullanışlı, ancak kaldırılmış dosyalar için çalışmıyor gibi görünüyor git rm ikincisi, OP'nin sorduğu şeydir. - MarkHu


Az önce sildiğim bir dosyayı geri yüklemek için bu soruya geldim ama henüz değişikliği yapmadım. Sadece kendinizi bu durumda bulursanız, yapmanız gereken tek şey şudur:

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


100
2018-04-10 00:03



Teşekkürler. Benim için çalışıyor. Henüz değişikliği yapmadığım bir dosyayı geri yükleyin. - Hua Zhang
Bu en basit ve en iyisi. - SmallChess


Eğer deli isen, kullan git-bisect. İşte yapılacaklar:

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

Şimdi otomatik testi çalıştırma zamanı. Kabuk komutu '[ -e foo.bar ]' 0 dönecekse foo.bar Varsa ve 1 aksi halde. "Koş" komutu git-bisect Testin başarısız olduğu ilk işlemi otomatik olarak bulmak için ikili aramayı kullanır. Verilen aralığın yarısından itibaren başlar (iyi ila kötü arasında) ve belirtilen testin sonucuna göre yarıya kadar keser.

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

Şimdi onu sildiğin işin başındasın. Buradan geleceğe geri sıçrayabilir ve kullanabilirsiniz git-revert değişimi geri almak için

git bisect reset
git revert <the offending commit>

veya bir taahhüdü geri alabilir ve hasarı manuel olarak inceleyebilirsiniz:

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

82
2018-06-04 22:46



Detay verir misin git bisect run '[ -e foo.bar ]'? - avdgaag
Otomatik olarak kontrol edilemeyen bir şey varsa, el ile iyi ve kötü de kullanabilirsiniz. Bisect man sayfasına bakınız. - Josh Lee
En kolay çözüm değil, ama oldukça etkileyici. Yazdığın için teşekkürler. - avdgaag
@avdgaag git bisect run Git komutunun, komutun döndürülmesi gereken yerde 'çalıştır' komutunu çalıştırarak otomatikleştirmesini söyler. 0 bir için good versiyon (bkz. git help bisect detaylar için). '[ -e foo.bar ]' dosya test için standart bir ifadedir foo.bar var (uygulama genellikle dosyada /usr/bin/[ genellikle /usr/bin/test) ve tek tırnak işaretleri tümünü tek bir komut satırı argümanı olarak koymak için kullanılır. - Mikko Rantalainen


Yeni favori takma ismime dayanarak bonyiii'ler Cevap (upvoted) ve kendi cevabım hakkında "Git takma komutuna bir argüman iletin":

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'

Bir dosyayı kaybettim, birkaç taahhüt önce yanlışlıkla silindi?
Hızlı:

git restore my_deleted_file

Kriz önlendi.


Robert Dailey önermektedir yorumlarda aşağıdaki diğer adlar:

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

Ve jegan ekler yorumlarda:

Diğer adı komut satırından ayarlamak için şu komutu kullandım:

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

61
2018-02-17 15:33



Bu, yalnızca istenen dosyayı değil, tüm işlemi geri yükler. - Daniel Bang
İşte benim takma ismim, harika çalışıyor: restore-file = !git checkout $(git rev-list -n 1 HEAD -- "$1")^ -- "$1" - void.pointer
@RobertDailey Bu harika görünüyor! Daha fazla görünürlük için takma adınızı ekledim. - VonC
git: 'geri yükle' bir git komutu değil. - resultsway
Diğer adı komut satırından ayarlamak için şu komutu kullandım: git config --global alias.restore "\!git checkout \$(git rev-list -n 1 HEAD -- \"\$1\")^ -- \"\$1\"" - jegan


Dosya adını biliyorsanız, bu temel komutlarla kolay bir yoldur:

Bu dosya için tüm taahhütleri listeleyin.

git log -- path/to/file

Son işlem (en üstteki) dosyayı silen dosyadır. Bu yüzden, son taahhüdü geri yüklemek için ihtiyacın var.

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

42
2018-02-27 01:50



Evet. Bu benim için doğru çözüm! Basit ve temizle - Fabrizio Bertoglio
Sadece bu çözümü kullandı ve silme için bir taahhüt yoktu. Ancak, en son taahhüt id'i kullanarak dosyayı geri yükleyebildim. - Adam
İçin +10 second to last commit açıklama! - colminator
Bir sonraki son taahhüt (silme işlemine önceki işlem), silinen dosyanın en son sürümünü içermez mi? İkinci olarak (silme işlemine önceki taahhütte bulunmadan), umutsuzca modası geçmiş olabilirdi. - Suncat2000
Bu gördüğüm ilk çözüm, bir dahaki sefere burayı bulmak için buraya gelmem gerekmeyecek kadar basit. Olabilir. - Eloff


Silinen ve işlenmiş bir dosyayı geri yüklemek için:

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

Git sürümü 1.7.5.4'te test edildi.


27
2017-07-04 04:39



Bu benim için çalışmadı. Ödeme yapıldıktan sonra error: pathspec 'foo' did not match any file(s) known to git. Dosya adının doğru olduğundan emin oldum. Git sürümü 2.7.0 - wisbucky
1; Bu yanlış. Bu komutlar bir silme işlemini geri alacaktır. henüz işlenmedi (birincisi, silinirse, silinirse, ikincisi ise dosyada talihsiz değişiklikler yapılmazsa), ancak burada bir taahhüt Dosyanın silinmesi, sadece doğru değildir ve @ wisbucky'nin yukarıdaki gibi bir hatayla başarısız olur. - Mark Amery
@MarkAmery Gerçekten, bu komut, kaldırılmış dosyalar için taahhütte bulunmak için açık bir şekilde aşamalandırmayan geliştiriciler için iyi çalıştı. git add -AAncak, geri yüklenen dosya hala taahhüt edilmemiş bir aşamadaydı. - Fedir RYKHTIK


Yalnızca bir değişiklik yaptıysanız ve bir dosyayı sildiyseniz, ancak onu işlemezseniz ve şimdi değişikliklerinizi yaptınız.

git checkout -- .

ancak silinen dosyalarınız geri gelmedi, sadece aşağıdaki komutu yapın:

git checkout <file_path>

Ve önceden, senin dosyan geri döndü.


21
2017-09-02 15:30





sahibim bu çözüm.

  1. Aşağıdaki yollardan birini kullanarak dosyanın silindiği işlemin kimliğini öğrenin.

    • git log --grep=*word* 
    • git log -Sword
    • git log | grep --context=5 *word*
    • git log --stat | grep --context=5 *word* # çok zorlanırsan bir şey hatırla
  2. Şunun gibi bir şey almalısın:

taahhüt bfe68bd117e1091c96d2976c99b3bcc8310bebe7 Yazar: Alexander   Orlov Tarih: Perşembe 12 Mayıs 23:44:27   0200

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

3ea4e3af253ac6fd1691ff6bb89c964f54802302 işlemek için Yazar: Alexander   Orlov Tarih: Perşembe 12 Mayıs 22:10:22   0200

3. Şimdi bfe68bd117e1091c96d2976c99b3bcc8310bebe7 işlem kimliğini kullanarak şunu yapın:

git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java

Commit kimliği dosyanın zaten silinmiş olduğu başvuruya gönderme yaparken, bfe68b'den hemen önce taahhütte bulunarak başvuruda bulunmanız gerekir. ^1. Bu şu anlama gelir: bfe68b'den hemen önce taahhüt ver.


20
2018-03-01 10:48



Bu kabul edilen cevapla aynı yaklaşımdır, ancak silme işlemini bulmak için daha fazla yolla. Yine de kabul edilen cevapta alınan yaklaşımı seviyorum ama bunlar iyi alternatifler. Teşekkürler! - avdgaag
Önce silinen dosyayı kontrol edip sonra (değiştirmeden) taahhütte bulunmanın bir kopya dosyanın Sağ? (Bunu resimlerle yapmam gerekiyor ve bir kopya depoyu büyütüyordu) - Stonecrusher