Come trovare un file eliminato nella cronologia del commit del progetto?


1275

C'era una volta un file nel mio progetto che ora vorrei poter ottenere.

Il problema è: non ho idea di quando l'ho eliminato e su quale percorso fosse.

Come posso individuare i commit di questo file quando esisteva?




13
Le risposte qui sono più utili per me delle risposte nei duplicati .
Felipe Alvarez,

5
d'accordo ... a prescindere dai duplicati ... non sono emersi nella ricerca di Google .... questo ha fatto ... spero che smetteremo di perdere tempo a cercare i duplicati ... solo il tempo e l'algoritmo di Google dì quale domanda è la migliore.
Tim Boland,

Risposte:


1601

Se non conosci il percorso esatto che puoi utilizzare

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

Se conosci il percorso in cui si trovava il file, puoi farlo:

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

Questo dovrebbe mostrare un elenco di commit in tutti i rami che hanno toccato quel file. Quindi, puoi trovare la versione del file che desideri e visualizzarla con ...

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

O ripristinalo nella tua copia di lavoro con:

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

Nota il simbolo del punto di inserimento ( ^), che ottiene il checkout prima di quello identificato, poiché al momento del <SHA>commit il file viene eliminato, dobbiamo guardare il commit precedente per ottenere il contenuto del file eliminato


2
Prova a utilizzare un percorso relativo anziché uno assoluto (se non lo sei già).
Ambra,

63
E se non conoscessi il percorso esatto? Tutto quello che sai è il nome del file?
sacerdote

17
@PedroMorteRolo git log -- <path>non avrà output quando ci si trova in un ramo in cui il file non è mai esistito. Dovresti sempre usare git log --all -- <path>, per assicurarti di non perdere i cambiamenti avvenuti su altri rami. Il comando git log -- <path>può essere molto pericoloso se si dispone di più di un ramo e si tende a dimenticare percorsi e rami (come me) ed è anche pericoloso se si lavora con altri sviluppatori.
Piani cottura

4
@Amber, considera di aggiungere --all(grazie Philip ) alla tua git logrisposta, in modo che le persone non perdano modifiche e file su altri rami. Ciò salverebbe molto il dolore alle persone smemorate come me.
Piani cottura

3
Come indicato nella risposta di seguito, il ripristino del file dovrebbe essere git checkout <SHA>^ -- <path-to-file>(notare il simbolo ^), poiché al momento del <SHA> il commit del file è stato cancellato, dobbiamo guardare al commit precedente per ottenere il contenuto del file cancellato
kipelovets

393

Ottieni un elenco dei file eliminati e copia il percorso completo del file eliminato

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

Eseguire il comando successivo per trovare l'ID commit di quel commit e copiare l'id commit

git log --all -- FILEPATH

Mostra diff del file eliminato

git show COMMIT_ID -- FILE_PATH

Ricorda, puoi scrivere l'output in un file usando >like

git show COMMIT_ID -- FILE_PATH > deleted.diff

1
Anche se ho trovato il percorso con l'aiuto del primo passo, il secondo passo getta questo errore: unknown revision or path not in the working tree.
jvannistelrooy,

6
Per vedere gli hash di commit insieme alle eliminazioni, puoi faregit log --diff-filter=D --summary | grep -E 'delete|^commit\s+\S+'
Chris Middleton il

1
Il passaggio 2 non restituisce nulla. Qualche idea sul perché possa accadere? Il mio nome file è corretto.
Denis Kniazhev,

2
Per trovare unisci i tre in una funzione, aggiungilo nel tuo .bashrc o .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; }e ora puoi semplicemente fare:git-grep-latest some_text
randomor

1
@TylerJones puoi alimentare qualsiasi cosa con linux usando pipe - google linux pipes.. ti piacerà.
John Hunt,

37

Impossibile modificare la risposta accettata, quindi aggiungendola come risposta qui,

per ripristinare il file in git, utilizzare quanto segue (notare il segno '^' subito dopo SHA)

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

Non capisco perché vorresti il ​​^. Il file è nel commit con quel SHA ... perché dovresti voler tornare indietro da un altro commit?
Tony K.

19
È nel commit con quella sha come "cancellato", il che significa che non esisterà ancora. Devi andare al commit prima di farlo per riaverlo.
tandrewnichols,

6
@tandrewnichols che significa solo che stai usando il commit SHA sbagliato: vuoi il commit per la versione del file che desideri ... che probabilmente non è la versione in cui il file viene eliminato.
Ambra

6
@Amber e il commit che desideri è probabilmente il più recente prima che fosse eliminato, quindi questa risposta.
Sam Holder

1
@AlexR: <SHA>~1dovrebbe funzionare allo stesso modo senza la necessità di avvolgerlo tra virgolette.
CodeManX,

37

Supponiamo che tu voglia recuperare un file chiamato MyFile, ma non sei sicuro del suo percorso (o della sua estensione, del resto):

Prelim .: Evita la confusione avvicinandoti alla radice git

Un progetto non banale può avere più directory con nomi simili o identici.

> cd <project-root>
  1. Trova il percorso completo

    git log --diff-filter = D --summary | grep elimina | grep MyFile

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

full/path/to/MyFile.js è il percorso e il file che stai cercando.

  1. Determina tutti i commit che hanno interessato quel file

    git log --oneline --follow - full / path / to / 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. Guarda il file

Se si sceglie il commit elencato per primo (l'ultimo in ordine cronologico, qui bd8374c), il file non verrà trovato, poiché è stato eliminato in quel commit.

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

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

Basta selezionare il commit precedente (aggiungi un cursore):

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

3
Questo è molto più chiaro della risposta accettata
Pouyan Khodabakhsh

per la console di Windows (cmd), utilizzare trova invece di grep nel passaggio 2: git log --diff-filter=D --summary | find "delete" | find "MyFile"E il passaggio 3 , notare le virgolette attorno all'hash:git checkout "bd8374c^" -- full/path/to/MyFile.js
user5542121

30

@Amber ha dato la risposta corretta! Ancora un'altra aggiunta, se non conosci il percorso esatto del file puoi usare i caratteri jolly! Questo ha funzionato per me.

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

4
@PedroMorteRolo Hmm. Non so come mi sento di copiare una risposta esistente nella prima votata: / Anche questa risposta è stata utile da sola; un voto potrebbe essere bastato?
Clément,

1
Questo non trova il file se si trova nella radice del progetto (testato in Cygwin).
Wortwart,

19

Di seguito è riportato un semplice comando, in cui un utente dev o un utente git può passare un nome file eliminato dalla directory principale del repository e ottenere la cronologia:

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

Se qualcuno, può migliorare il comando, per favore fallo.


1
Fantastico, grazie! Sembra che il mio file non sia mai esistito, ma questo è un problema separato e molto più peloso ...

assicurati di eseguirlo dalla directory principale del repository se il tuo file sembra essere "mancante"
samaspin

Grazie @samaspin ha aggiornato la risposta.
Jason,

18

Prova a utilizzare uno dei visualizzatori, ad esempio in gitkmodo da poter sfogliare la cronologia per trovare quel file ricordato per metà. (utilizzare gitk --allse necessario per tutti i rami)


4
Tale --allopzione è fondamentale sia per la risposta che per la risposta accettata.
Piani cottura

3
La navigazione nella cronologia richiederà uno straordinario tempo per la maggior parte dei progetti.
mikemaccana,

5

Sommario:

  1. Passo 1

Si cerca il percorso completo del file nella cronologia dei file eliminati git log --diff-filter=D --summary | grep filename

  1. Passo 2

Ripristini il tuo file dal commit prima che fosse eliminato

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

0

Ecco la mia soluzione:

git log --all --full-history --oneline -- <RELATIVE_FILE_PATH>
git checkout <COMMIT_SHA>^ -- <RELATIVE_FILE_PATH>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.