0%

Änderungen rückgängig machen · Übung

Ich habe etwas ausgeführt und jetzt ist meine Arbeit weg

Etwas, das du committet hattest, ist nicht mehr da. Ein Befehl, den du nur halb verstanden hast, hat etwas Unerwartetes getan. Ein Stück echter Arbeit ist aus git log verschwunden. Diesen Moment beschreiben Menschen als einen verlorenen Arbeitstag.

Der Commit könnte noch verfügbar sein, auch wenn dein Branch ihn nicht mehr enthält. Diese Lektion zeigt, wie du nach ihm suchst und seine Arbeit wiederherstellst.

Zuerst die verfolgten Dateien in einen sicheren Zustand bringen

Bringe den Wanderführer vor der Wiederherstellung der fehlenden Arbeit in einen sicheren Ausgangszustand. Vielleicht enthält route.txt noch eine unerwünschte Änderung und scratch.tmp ist noch bereitgestellt. Vielleicht hast du diese beiden Missgeschicke aber bereits behoben.

Diese ersten Befehle verwerfen den vorbereiteten Fehler in der Route. Verwende sie deshalb nur für dieses Übungsprojekt. Prüfe in deinem eigenen Repository git status und git diff, bevor du eine Änderung verwirfst, die du vielleicht brauchst.

git restore --staged . entfernt zuerst bereitgestellte Änderungen unterhalb des aktuellen Verzeichnisses aus der Momentaufnahme für den nächsten Commit. Der Punkt steht für dieses Verzeichnis und seine Unterverzeichnisse. Hier startet das Terminal im Projektwurzelverzeichnis. Das umfasst also das Projekt. Danach setzt git restore route.txt die verfolgte Routendatei auf die Version des neuesten Commits zurück. Keiner der beiden Befehle löscht scratch.tmp oder packing.txt.

git restore --staged .
git restore route.txt
git status

git status führt jetzt möglicherweise scratch.tmp und packing.txt als nicht verfolgt auf. Diese Dateien überschneiden sich nicht mit der fehlenden Wetterdatei und können während der Wiederherstellung sicher daneben liegen bleiben. Es sollte keine bereitgestellte Änderung und keine geänderte verfolgte Datei geben.

Die fehlende Arbeit

Der Wanderführer hatte einen Abschnitt über das Wetter im Tal: ein paar Absätze darüber, dass die Wolken bis mittags bleiben, und welcher Vorhersage man vertrauen kann. Der Shell-Befehl ls listet die Namen im aktuellen Verzeichnis auf. Verwende ihn zusammen mit dem Verlauf, um sowohl nach dem Commit als auch nach der Datei zu suchen:

git log
ls

Der Commit steht nicht im Verlauf, und weather.md liegt nicht auf dem Datenträger. Irgendwann hat jemand git reset --hard ausgeführt. Das setzt den Branch zurück und überschreibt den Arbeitsbaum passend dazu. Der Commit gehörte danach nicht mehr zum Branch, und mit den gewöhnlichen Möglichkeiten zum Nachsehen scheint er verschwunden zu sein.

Git führt Tagebuch

Hier kommt der Teil, den fast niemand erklärt bekommt: Git führt lokale Protokolle der jüngsten Verschiebungen von Referenzen. Diese Aufzeichnungen heißen Reflogs. Ein einfaches git reflog zeigt die jüngsten Positionen, die HEAD in diesem Repository hatte.

git reflog

Der neueste Eintrag steht oben. Von unten nach oben gelesen erzählen die Einträge also die Geschichte des Repositorys. Wenn du die vorherigen Lektionen durchgearbeitet hast, stehen deine eigenen amend-, reset- und revert-Aktionen über den älteren vorbereiteten Einträgen. Das sind nützliche Belege, kein Ballast: Das Reflog zeichnet auf, was in diesem lokalen Repository tatsächlich passiert ist.

Suche den Eintrag mit der Bezeichnung commit: Write up the weather section. Die vorbereitete Zeile reset: moving to HEAD~1 direkt darüber markiert den Moment, in dem Git diesen Commit verlassen hat. Es könnte einen neueren Reset aus der früheren Lektion zu privaten Commits geben. Deshalb identifiziert die Wetterbezeichnung die gesuchte Arbeit, nicht bloß das Wort reset.

Jede Zeile beginnt mit einer kurzen Kennung und trägt außerdem einen Namen der Form HEAD@{n}. Er bedeutet „wo HEAD vor n Verschiebungen stand“. Die Zahl hängt davon ab, was du in dieser Arbeitsumgebung getan hast. Beide Namen im Wettereintrag bezeichnen diesen Commit.

In diesem vorbereiteten Repository existiert der Commit noch, obwohl kein Branch auf ihn zeigt. Das Reflog liefert eine Kennung, mit der du ihn erreichen kannst.

Die Arbeit zurückholen

Du möchtest die Arbeit dieses Commits in deinem aktuellen Branch haben. git cherry-pick nimmt einen Commit von irgendeiner Stelle im Repository und wendet ihn auf deinen jetzigen Stand an:

git cherry-pick 3e78e25
git log
ls

Diese Kennung steht in der Zeile commit: Write up the weather section. Sie ist hier für alle gleich, weil jeder Lernende mit demselben vorbereiteten Repository beginnt. In deinen eigenen Projekten wird sie jedes Mal anders sein. Gewöhne dir deshalb an, sie aus deinem eigenen git reflog abzulesen, statt sie dir zu merken.

git log zeigt den Wetterabschnitt jetzt wieder im Verlauf. weather.md liegt mit seinen vollständigen Absätzen auf dem Datenträger. Die Arbeit war die ganze Zeit noch da.

Was dabei zerstört wird und was nicht

git reflog liest nur. Es verändert überhaupt nichts, und du kannst es beliebig oft ausführen. Wenn du Angst hast, führe es zuerst aus.

git cherry-pick erstellt einen Commit auf deinem aktuellen Branch, ohne die Commits umzuschreiben, die bereits in dessen erreichbarem Verlauf liegen. Auch der Quellcommit bleibt unverändert.

Zwei Grenzen sind wichtig. Das Reflog ist lokal: Es beschreibt dein Repository, nicht das einer anderen Person. Ein frischer Klon hat sein eigenes Reflog. Einträge können ablaufen, und beim Aufräumen des Repositorys können Commits entfernt werden, die nicht mehr aufbewahrt werden. Einstellungen und Aufräumvorgänge beeinflussen, wie lange eine Wiederherstellung möglich bleibt. Untersuche den Fall deshalb zeitnah, statt dich auf eine garantierte Anzahl von Wochen zu verlassen. Diese Methode kann außerdem keine Bearbeitungen wiederherstellen, die Git nie aufgezeichnet hat.

Die nützliche Gewohnheit lautet: erst prüfen, dann wieder etwas ändern. Ein fehlender Eintrag in git log ist ein Anlass, git reflog zu prüfen, den gewünschten Commit zu identifizieren und ihn wiederherzustellen, solange er noch verfügbar ist.

Du setzt einen Branch zurück und verlierst einen Commit. Dann führst du ein einfaches git reflog aus. Was siehst du?

Das war das Kapitel. Sechs Fragen, sechs Antworten und eine gemeinsame Idee: Git fügt viel häufiger etwas hinzu, als es etwas entfernt. Was zerstört aussieht, ist meist nur nicht mehr referenziert.