Wie finde ich eine gelöschte Datei im Projekt-Commit-Verlauf?

1274

Es war einmal eine Datei in meinem Projekt, die ich jetzt gerne bekommen würde.

Das Problem ist: Ich habe keine Ahnung, wann ich es gelöscht habe und auf welchem ​​Pfad es war.

Wie kann ich die Commits dieser Datei finden, wenn sie vorhanden war?

Pedro Rolo
quelle
Ähnliche Frage hier: stackoverflow.com/questions/7093602/…
eckes
3
Mögliches Duplikat von Find, wenn eine Datei in Git gelöscht wurde
Dan Dascalescu
13
Die Antworten hier sind für mich nützlicher als die Antworten in den Duplikaten .
Felipe Alvarez
5
vereinbart ... unabhängig von den Duplikaten ... sie sind nicht in der Google-Suche aufgetaucht ... diese haben es getan ... ich hoffe, wir werden keine Zeit mehr damit verschwenden, Duplikate zu verfolgen ... nur Zeit und Googles Algorithmus werden es tun Sagen Sie, welche Frage die beste ist.
Tim Boland

Antworten:

1600

Wenn Sie den genauen Pfad nicht kennen, können Sie ihn verwenden

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

Wenn Sie den Pfad der Datei kennen, können Sie Folgendes tun:

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

Dies sollte eine Liste von Commits in allen Zweigen anzeigen, die diese Datei berührt haben. Anschließend können Sie die gewünschte Version der Datei finden und mit ...

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

Oder stellen Sie es in Ihrer Arbeitskopie wieder her mit:

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

Beachten Sie das Caret-Symbol ( ^), das die Prüfung vor dem identifizierten Symbol erhält , da zum Zeitpunkt des <SHA>Festschreibens die Datei gelöscht wird. Wir müssen uns das vorherige Festschreiben ansehen, um den Inhalt der gelöschten Datei zu erhalten

Bernstein
quelle
2
Versuchen Sie, einen relativen Pfad anstelle eines absoluten zu verwenden (falls Sie dies noch nicht getan haben).
Amber
63
Was ist, wenn Sie den genauen Weg nicht kennen? Alles was Sie wissen ist der Dateiname?
Priester
17
@PedroMorteRolo git log -- <path>hat keine Ausgabe, wenn Sie sich in einem Zweig befinden, in dem die Datei nie existiert hat. Sie sollten immer verwenden git log --all -- <path>, um sicherzustellen, dass Sie keine Änderungen verpassen, die in anderen Zweigen vorgenommen wurden. Der Befehl git log -- <path>kann sehr gefährlich sein, wenn Sie mehr als einen Zweig haben und dazu neigen, Pfade und Zweige (wie ich) zu vergessen, und er ist auch gefährlich, wenn Sie mit anderen Entwicklern zusammenarbeiten.
Kochfelder
4
@Amber, erwägen Sie , Ihrer Antwort etwas hinzuzufügen --all(danke Philip ) git log, damit die Leute keine Änderungen und Dateien in anderen Zweigen verpassen. Es würde vergesslichen Menschen wie mir viel Kummer ersparen.
Kochfelder
3
Wie in der folgenden Antwort angegeben, sollte die Wiederherstellung der Datei wie folgt erfolgen git checkout <SHA>^ -- <path-to-file>(beachten Sie das Symbol ^), da zum Zeitpunkt des
Festschreibens
393

Rufen Sie eine Liste der gelöschten Dateien ab und kopieren Sie den vollständigen Pfad der gelöschten Datei

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

Führen Sie den nächsten Befehl aus, um die Festschreibungs-ID dieses Festschreibens zu ermitteln, und kopieren Sie die Festschreibungs-ID

git log --all -- FILEPATH

Diff der gelöschten Datei anzeigen

git show COMMIT_ID -- FILE_PATH

Denken Sie daran, dass Sie die Ausgabe mit >like in eine Datei schreiben können

git show COMMIT_ID -- FILE_PATH > deleted.diff
Fatih Acet
quelle
1
Obwohl ich den Pfad mithilfe des ersten Schritts gefunden habe, löst der zweite Schritt diesen Fehler aus : unknown revision or path not in the working tree.
Jvannistelrooy
6
Um die Commit-Hashes zusammen mit den Löschvorgängen zu sehen, können Sie Folgendes tungit log --diff-filter=D --summary | grep -E 'delete|^commit\s+\S+'
Chris Middleton,
1
Schritt 2 gibt nichts zurück. Irgendwelche Ideen, warum es passieren kann? Mein Dateiname ist korrekt.
Denis Kniazhev
2
Um die drei zu einer Funktion zu kombinieren, fügen Sie diese zu Ihrer .bashrc oder .zshrc hinzu: 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; }und jetzt können Sie einfach Folgendes tun:git-grep-latest some_text
randomor
1
@ TylerJones Sie können alles unter Linux mit Pipes füttern - google linux pipes.. das wird Ihnen gefallen.
John Hunt
37

Die akzeptierte Antwort konnte nicht bearbeitet werden. Fügen Sie sie hier als Antwort hinzu.

Verwenden Sie Folgendes, um die Datei in git wiederherzustellen (beachten Sie das Zeichen '^' direkt nach dem SHA).

git checkout <SHA>^ -- /path/to/file
Akshay Agarwal
quelle
Ich verstehe nicht, warum du das ^ willst. Die Datei befindet sich im Commit mit diesem SHA ... warum sollten Sie von dort aus ein weiteres Commit zurückgehen?
Tony K.
19
Es ist im Commit mit diesem sha als "gelöscht", was bedeutet, dass es immer noch nicht existiert. Sie müssen vorher zum Commit gehen, um es tatsächlich zurückzubekommen.
Tandrewnichols
6
@tandrewnichols, was nur bedeutet, dass Sie das falsche Commit-SHA verwenden - Sie möchten das Commit für die Version der gewünschten Datei ... was wahrscheinlich nicht die Version ist, in der die Datei gelöscht wird.
Amber
6
@Amber und das gewünschte Commit ist wahrscheinlich das aktuellste, bevor es gelöscht wurde, daher diese Antwort.
Sam Holder
1
@AlexR: <SHA>~1sollte genauso funktionieren, ohne dass Anführungszeichen erforderlich sind.
CodeManX
37

Angenommen, Sie möchten eine aufgerufene Datei wiederherstellen MyFile, sind sich jedoch ihres Pfads (oder ihrer Erweiterung) nicht sicher:

Prelim.: Vermeiden Sie Verwirrung, indem Sie zur Git-Wurzel treten

Ein nicht triviales Projekt kann mehrere Verzeichnisse mit ähnlichen oder identischen Namen haben.

> cd <project-root>
  1. Finde den vollständigen Pfad

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

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

full/path/to/MyFile.js ist der Pfad und die Datei, die Sie suchen.

  1. Bestimmen Sie alle Commits, die diese Datei betroffen haben

    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. Überprüfen Sie die Datei

Wenn Sie das zuerst aufgeführte Commit auswählen (das letzte chronologisch, hier bd8374c), wird die Datei nicht gefunden, da sie in diesem Commit gelöscht wurde.

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

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

Wählen Sie einfach das vorhergehende Commit (Caret anhängen) aus:

> git checkout bd8374c^ -- full/path/to/MyFile.js
Calaf
quelle
3
Dies ist viel klarer als die akzeptierte Antwort
Pouyan Khodabakhsh
Verwenden Sie für die Windows-Konsole (cmd) in Schritt 2 find anstelle von grep: git log --diff-filter=D --summary | find "delete" | find "MyFile"Beachten Sie in Schritt 3 die Anführungszeichen um den Hash:git checkout "bd8374c^" -- full/path/to/MyFile.js
user5542121
30

@ Amber gab die richtige Antwort! Nur noch eine Ergänzung: Wenn Sie den genauen Pfad der Datei nicht kennen, können Sie Platzhalter verwenden! Das hat bei mir funktioniert.

git log --all -- **/thefile.*
Petur Subev
quelle
4
@ PedroMorteRolo Hmm. Ich weiß nicht, wie ich es finde, eine vorhandene Antwort in die am besten gewählte zu kopieren: / Diese Antwort war auch für sich allein nützlich; eine Gegenstimme hätte reichen können?
Clément
1
Die Datei wird nicht gefunden, wenn sie sich im Projektstamm befindet (getestet in Cygwin).
Wortwart
19

Im Folgenden finden Sie einen einfachen Befehl, mit dem ein Entwickler oder ein Git-Benutzer einen gelöschten Dateinamen aus dem Repository-Stammverzeichnis übergeben und den Verlauf abrufen kann:

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

Wenn jemand den Befehl verbessern kann, tun Sie dies bitte.

Jason
quelle
1
Super, danke! Sieht so aus, als ob meine Datei überhaupt nicht existiert hätte, aber das ist ein separates und viel haarigeres Problem…
Stellen Sie sicher, dass Sie dies aus dem Repository-Stammverzeichnis ausführen, wenn Ihre Datei "fehlt"
Samaspin
Danke @samaspin hat die Antwort aktualisiert.
Jason
18

Versuchen Sie es mit einem der Viewer, z. B. gitkdamit Sie im Verlauf nach der halb gespeicherten Datei suchen können. ( gitk --allbei Bedarf für alle Filialen verwenden)

Philip Oakley
quelle
4
Diese --allOption ist sowohl für Ihre Antwort als auch für die akzeptierte Antwort von entscheidender Bedeutung.
Kochfelder
3
Das Durchsuchen der Geschichte nimmt für die meisten Projekte außerordentlich viel Zeit in Anspruch.
Mikemaccana
5

Zusammenfassung:

  1. Schritt 1

Sie durchsuchen den vollständigen Pfad Ihrer Datei im Verlauf gelöschter Dateien git log --diff-filter=D --summary | grep filename

  1. Schritt 2

Sie stellen Ihre Datei aus dem Commit wieder her, bevor sie gelöscht wurde

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
Srghma
quelle
0

Hier ist meine Lösung:

git log --all --full-history --oneline -- <RELATIVE_FILE_PATH>
git checkout <COMMIT_SHA>^ -- <RELATIVE_FILE_PATH>
Antonio Petricca
quelle