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.