Trova e ripristina un file eliminato in un repository Git

Dì che sono in un repository Git. Eliminare un file e confermare questa modifica. Continuo a lavorare e ad impegnarmi ancora di più. Quindi, trovo che ho bisogno di ripristinare quel file.

So che posso eseguire il checkout di un file usando git checkout HEAD^ foo.bar , ma non so davvero quando quel file è stato cancellato.

  1. Quale sarebbe il modo più rapido per trovare il commit che ha cancellato un determinato nome file?
  2. Quale sarebbe il modo più semplice per riportare il file nella mia copia di lavoro?

Spero di non dover scorrere manualmente i miei registri, controllare l’intero progetto per un dato SHA e quindi copiare manualmente il file nel mio checkout del progetto originale.

Trova l’ultimo commit che ha interessato il percorso specificato. Poiché il file non è nel commit HEAD, questo commit deve averlo eliminato.

 git rev-list -n 1 HEAD --  

Quindi verifica la versione al commit prima, usando il simbolo caret ( ^ ):

 git checkout ^ --  

O in un comando, se $file è il file in questione.

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

Se stai usando zsh e hai abilitato l’opzione EXTENDED_GLOB, il simbolo del punto di inserimento non funzionerà. Puoi usare ~1 invece.

 git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file" 
  1. Usa git log --diff-filter=D --summary per ottenere tutti i commit che hanno cancellato i file ei file cancellati;
  2. Usa git checkout $commit~1 filename per ripristinare il file cancellato.

Dove $commit è il valore del commit che hai trovato nel passaggio 1, ad esempio e4cf499627

Per ripristinare tutti i file eliminati in una cartella, immettere il seguente comando.

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

Sono arrivato a questa domanda cercando di ripristinare un file che ho appena cancellato ma non avevo ancora commesso il cambiamento. Nel caso in cui ti trovi in ​​questa situazione, tutto ciò che devi fare è il seguente:

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

Se sei pazzo, usa git-bisect . Ecco cosa fare:

 git bisect start git bisect bad git bisect good  

Ora è il momento di eseguire il test automatico. Il comando shell '[ -e foo.bar ]' restituirà 0 se foo.bar esiste, e 1 altrimenti. Il comando “run” di git-bisect utilizzerà la ricerca binaria per trovare automaticamente il primo commit in cui il test fallisce. Inizia a metà dell’intervallo assegnato (da buono a cattivo) e lo taglia a metà in base al risultato del test specificato.

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

Ora sei al commit che l’ha cancellato. Da qui, puoi tornare al futuro e usare git-revert per annullare la modifica,

 git bisect reset git revert  

oppure puoi tornare indietro di un commit e ispezionare manualmente il danno:

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

Il mio nuovo alias preferito, basato sulla risposta di bonyiii (upvoted), e la mia risposta su ” Passa un argomento ad un comando 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' 

Ho perso un file, cancellato per sbaglio qualche commit fa?
Presto:

 git restore my_deleted_file 

Crisi evitata.


Robert Dailey propone nei commenti il seguente alias:

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

E jegan aggiunge nei commenti :

Per impostare l’alias dalla riga di comando, ho usato questo comando:

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

Se conosci il nome del file, questo è un modo semplice con i comandi di base:

Elenca tutti i commit per quel file.

 git log -- path/to/file 

L’ultimo commit (in alto) è quello che ha cancellato il file. Quindi è necessario ripristinare il penultimo commit.

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

Per ripristinare un file cancellato e triggersto:

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

È stato testato su Git versione 1.7.5.4.

Se hai apportato solo modifiche e cancellato un file, ma non lo hai commesso, ora hai interrotto le modifiche

 git checkout -- . 

ma i tuoi file cancellati non sono tornati, devi semplicemente eseguire il seguente comando:

 git checkout  

E presto, il tuo file è tornato.

Ho questa soluzione .

  1. Ottieni l’ID del commit in cui il file è stato eliminato utilizzando uno dei seguenti modi.

    • git log --grep=*word*
    • git log -Sword
    • git log | grep --context=5 *word*
    • git log --stat | grep --context=5 *word* git log --stat | grep --context=5 *word* # raccomandato se non ricordi quasi nulla
  2. Dovresti ottenere qualcosa del tipo:

commit bfe68bd117e1091c96d2976c99b3bcc8310bebe7 Autore: Alexander Orlov Data: gio 12 maggio 23:44:27 2011 +0200

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

commit 3ea4e3af253ac6fd1691ff6bb89c964f54802302 Autore: Alexander Orlov Data: gio 12 maggio 22:10:22 2011 +0200

3 . Ora usando l’id di commit bfe68bd117e1091c96d2976c99b3bcc8310bebe7 fai:

 git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java 

Siccome l’id di commit fa riferimento al commit in cui il file è stato già eliminato, devi fare riferimento al commit appena prima di bfe68b che puoi fare aggiungendo ^1 . Questo significa: dammi il commit subito prima di bfe68b.

 git checkout /path/to/deleted.file 

In molti casi, può essere utile utilizzare coreutils (grep, sed, ecc.) Insieme a Git. Conosco già abbastanza bene questi strumenti, ma meno male. Se volessi fare una ricerca per un file cancellato, farei quanto segue:

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

Quando trovo la revisione / commit:

 git checkout ^ -- path/to/refound/deleted_file.c 

Proprio come hanno affermato altri prima di me.

Il file verrà ripristinato allo stato che aveva prima della rimozione. Ricordati di re-impegnarlo nell’albero di lavoro se vuoi tenerlo in giro.

git undelete path/to/file.ext

  1. Metti questo nel tuo .bash_profile (o altro file rilevante che viene caricato quando apri una shell di comandi):

     git config --global alias.undelete '!sh -c "git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1" -' 
  2. Quindi utilizzare:

     git undelete path/to/file.ext 

Questo alias controlla prima di trovare l’ultimo commit in cui questo file esiste, quindi esegue un checkout git di quel percorso file dall’ultimo commit in cui questo file è esistito. fonte

Quindi ho dovuto ripristinare un gruppo di file cancellati da uno specifico commit e l’ho gestito con due comandi:

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

(Nota lo spazio finale alla fine di ogni comando.)

I file sono stati aggiunti al file .gitignore e quindi cancellati con git rm, avevo bisogno di ripristinare i file ma poi di metterli fuori scena. Ho avuto centinaia di file da ripristinare, digitando le cose manualmente per ogni file, come negli altri esempi sarebbe stato troppo lento.

 [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 

Ripristina il file cancellato:

 [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 

Nel nostro caso abbiamo cancellato accidentalmente dei file in un commit e alcuni hanno commesso in seguito, ci siamo resi conto del nostro errore e volevamo recuperare tutti i file eliminati ma non quelli modificati.

Basato sull’eccellente risposta di Charles Bailey, ecco il mio unico rivestimento:

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

Se si conosce il commit che ha eliminato il file (s), eseguire questo comando dove è il commit che ha eliminato il file:

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

La parte prima della pipe elenca tutti i file che sono stati cancellati nel commit; sono tutti checkout dal commit precedente per ripristinarli.

Ho avuto la stessa domanda. Senza saperlo, avevo creato un impegno penzolante .

Elenco pende penzoloni

git fsck --lost-found

Ispeziona ogni impegno penzolante

git reset --hard

I miei file sono riapparsi quando sono passato al commit penzolante.

git status per il motivo:

“HEAD detached from

 $ git log --diff-filter=D --summary | grep "delete" | sort