Als Entwickler arbeiten Sie ständig mit Git.
Sind Sie jemals an einen Punkt gekommen, an dem Sie gesagt haben: „Oh-oh, was habe ich gerade gemacht?“
Dieser Beitrag gibt Ihnen die Werkzeuge an die Hand, mit denen Sie die Geschichte selbstbewusst neu schreiben können.
Ich habe auch einen Live-Vortrag über den Inhalt dieses Beitrags gehalten. Wenn Sie ein Video bevorzugen (oder es neben der Lektüre ansehen möchten), können Sie es finden
Ich arbeite an einem Buch über Git! Sind Sie daran interessiert, die ersten Versionen zu lesen und Feedback zu geben? Schicken Sie mir eine E-Mail: [email protected]
Bevor Sie verstehen, wie man Dinge in Git rückgängig macht , sollten Sie zunächst verstehen, wie wir Änderungen in Git aufzeichnen . Wenn Sie bereits alle Begriffe kennen, können Sie diesen Teil gerne überspringen.
Es ist sehr nützlich, sich Git als ein System zum zeitlichen Aufzeichnen von Snapshots eines Dateisystems vorzustellen. Betrachtet man ein Git-Repository, so hat es drei „Zustände“ oder „Bäume“:
Wenn wir an unserem Quellcode arbeiten, arbeiten wir normalerweise von einem Arbeitsverzeichnis aus. Ein Arbeitsverzeichnis (oder Arbeitsbaum ) ist ein beliebiges Verzeichnis in unserem Dateisystem, dem ein Repository zugeordnet ist.
Es enthält die Ordner und Dateien unseres Projekts sowie ein Verzeichnis namens .git
. Den Inhalt des .git
Ordners habe ich in ausführlicher beschrieben
Nachdem Sie einige Änderungen vorgenommen haben, möchten Sie diese möglicherweise in Ihrem Repository aufzeichnen. Ein Repository (kurz: Repo ) ist eine Sammlung von Commits , von denen jeder ein Archiv davon ist, wie der Arbeitsbaum des Projekts zu einem früheren Zeitpunkt aussah, sei es auf Ihrem Computer oder dem eines anderen.
Ein Repository umfasst auch andere Dinge als unsere Codedateien, wie z. B. HEAD
, Branches usw.
Dazwischen gibt es den Index oder den Staging-Bereich ; Diese beiden Begriffe sind austauschbar. Wenn wir einen Zweig checkout
, füllt Git den Index mit allen Dateiinhalten, die zuletzt in unser Arbeitsverzeichnis ausgecheckt wurden, und wie sie beim ursprünglichen Auschecken aussahen.
Wenn wir git commit
verwenden, wird das Commit basierend auf dem Status des Index erstellt.
Der Index bzw. der Staging-Bereich ist also Ihr Spielplatz für den nächsten Commit. Sie können mit dem Index arbeiten und machen, was Sie wollen, ihm Dateien hinzufügen, Dinge daraus entfernen und erst dann, wenn Sie bereit sind, mit der Übertragung an das Repository fortfahren.
Zeit zum Anfassen 🙌🏻
Verwenden Sie git init
, um ein neues Repository zu initialisieren. Schreiben Sie einen Text in eine Datei namens 1.txt
:
Wo befindet sich 1.txt
in den drei oben beschriebenen Baumzuständen jetzt?
Im Arbeitsbaum, da es noch nicht in den Index aufgenommen wurde.
Um es bereitzustellen und zum Index hinzuzufügen, verwenden Sie git add 1.txt
.
Jetzt können wir git commit
verwenden, um unsere Änderungen im Repository zu übernehmen.
Sie haben ein neues Commit-Objekt erstellt, das einen Zeiger auf einen Baum enthält, der den gesamten Arbeitsbaum beschreibt. In diesem Fall wird es nur 1.txt
im Stammordner sein. Zusätzlich zu einem Zeiger auf den Baum enthält das Commit-Objekt Metadaten wie Zeitstempel und Autoreninformationen.
Weitere Informationen zu den Objekten in Git (z. B. Commits und Bäume) finden Sie unter
(Ja, „check out“, Wortspiel beabsichtigt 😇)
Git teilt uns auch den SHA-1-Wert dieses Commit-Objekts mit. In meinem Fall war es c49f4ba
(das sind nur die ersten 7 Zeichen des SHA-1-Werts, um etwas Platz zu sparen).
Wenn Sie diesen Befehl auf Ihrem Computer ausführen, erhalten Sie einen anderen SHA-1-Wert, da Sie ein anderer Autor sind. Außerdem würden Sie den Commit mit einem anderen Zeitstempel erstellen.
Wenn wir das Repo initialisieren, erstellt Git einen neuen Zweig (standardmäßig main
genannt). Undmain
. Was passiert, wenn Sie mehrere Filialen haben? Woher weiß Git, welcher Zweig der aktive Zweig ist?
Git hat einen weiteren Zeiger namens HEAD
, der (normalerweise) auf einen Zweig zeigt, der dann auf einen Commit zeigt. Übrigens,HEAD
Zeit, weitere Änderungen am Repo vorzunehmen!
Jetzt möchte ich ein weiteres erstellen. Erstellen wir also eine neue Datei und fügen sie wie zuvor zum Index hinzu:
Jetzt ist es an der Zeit, git commit
zu verwenden. Wichtig ist, dass git commit
zwei Dinge bewirkt:
Zunächst wird ein Commit-Objekt erstellt, sodass es in der internen Objektdatenbank von Git ein Objekt mit einem entsprechenden SHA-1-Wert gibt. Dieses neue Commit-Objekt verweist auch auf das übergeordnete Commit. Das ist der Commit, auf den HEAD
hingewiesen hat, als Sie den Befehl git commit
geschrieben haben.
Zweitens verschiebt git commit
den Zeiger des aktiven Zweigs – in unserem Fall wäre das main
, um auf das neu erstellte Commit-Objekt zu zeigen.
Um die Geschichte neu zu schreiben, beginnen wir damit, den Prozess der Einführung eines Commits rückgängig zu machen. Dazu lernen wir den Befehl git reset
kennen, ein superleistungsfähiges Tool.
git reset --soft
Der allerletzte Schritt, den Sie zuvor gemacht haben, war also git commit
, was eigentlich zwei Dinge bedeutet: Git hat ein Commit-Objekt erstellt und main
, den aktiven Zweig, verschoben. Um diesen Schritt rückgängig zu machen, verwenden Sie den Befehl git reset --soft HEAD~1
.
Die Syntax HEAD~1
bezieht sich auf das erste übergeordnete Element von HEAD
. Wenn ich mehr als ein Commit im Commit-Diagramm hätte, sagen Sie „Commit 3“, was auf „Commit 2“ verweist, was wiederum auf „Commit 1“ verweist.
Und sagen wir, HEAD
zeigte auf „Commit 3“. Sie könnten HEAD~1
verwenden, um auf „Commit 2“ zu verweisen, und HEAD~2
würde sich auf „Commit 1“ beziehen.
Also zurück zum Befehl: git reset --soft HEAD~1
Dieser Befehl fordert Git auf, zu ändern, worauf HEAD
verweist. (Hinweis: In den Diagrammen unten verwende ich *HEAD
für „was auch immer HEAD
zeigt“). In unserem Beispiel zeigt HEAD
auf main
. Git ändert also nur den Zeiger von main
so, dass er auf HEAD~1
zeigt. Das heißt, main
zeigt auf „Commit 1“.
Dieser Befehl hatte jedoch keine Auswirkungen auf den Status des Index oder des Arbeitsbaums. Wenn Sie also git status
verwenden, werden Sie sehen, dass 2.txt
bereitgestellt wird, genau wie vor der Ausführung von git commit
.
Was ist mit git log?
Es beginnt bei HEAD
, geht zu main
und dann zu „Commit 1“. Beachten Sie, dass dies bedeutet, dass „Commit 2“ aus unserem Verlauf nicht mehr erreichbar ist.
Bedeutet das, dass das Commit-Objekt von „Commit 2“ gelöscht wird? 🤔
Nein, es ist nicht gelöscht. Es befindet sich weiterhin in der internen Objektdatenbank von Git.
Wenn Sie den aktuellen Verlauf jetzt mithilfe von git push
pushen, pusht Git „Commit 2“ nicht auf den Remote-Server, aber das Commit-Objekt ist weiterhin in Ihrer lokalen Kopie des Repositorys vorhanden.
Führen Sie nun erneut einen Commit durch – und verwenden Sie die Commit-Nachricht von „Commit 2.1“, um dieses neue Objekt vom ursprünglichen „Commit 2“ zu unterscheiden:
Warum sind „Commit 2“ und „Commit 2.1“ unterschiedlich? Auch wenn wir dieselbe Commit-Nachricht verwendet haben und obwohl sie darauf verweisen1.txt
und 2.txt
) haben sie dennoch unterschiedliche Zeitstempel, da sie zu unterschiedlichen Zeiten erstellt wurden.
In der Zeichnung oben habe ich „Commit 2“ beibehalten, um Sie daran zu erinnern, dass es immer noch in der internen Objektdatenbank von Git vorhanden ist. Sowohl „Commit 2“ als auch „Commit 2.1“ zeigen jetzt auf „Commit 1“, aber nur „Commit 2.1“ ist von HEAD
aus erreichbar.
Es ist an der Zeit, sogar noch einen Schritt zurückzugehen und noch mehr rückgängig zu machen. Verwenden Sie dieses Mal git reset --mixed HEAD~1
(Hinweis: --mixed
ist der Standardschalter für git reset
).
Dieser Befehl startet genauso wie git reset --soft HEAD~1
. Das heißt, es nimmt den Zeiger dessen, worauf HEAD
gerade zeigt, also den main
, und setzt ihn auf HEAD~1
, in unserem Beispiel – „Commit 1“.
Als nächstes geht Git noch einen Schritt weiter und macht die Änderungen, die wir am Index vorgenommen haben, effektiv rückgängig. Das heißt, den Index so ändern, dass er mit dem aktuellen HEAD
übereinstimmt, dem neuen HEAD
, nachdem er im ersten Schritt festgelegt wurde.
Wenn wir git reset --mixed HEAD~1
ausführen würden, bedeutet dies, dass HEAD
auf HEAD~1
(„Commit 1“) gesetzt würde und Git dann den Index dem Status „Commit 1“ zuordnen würde – in diesem Fall es bedeutet, dass 2.txt
nicht mehr Teil des Index ist.
Es ist Zeit, ein neues Commit mit dem Status des ursprünglichen „Commit 2“ zu erstellen. Dieses Mal müssen wir 2.txt
erneut bereitstellen, bevor wir es erstellen:
Mach weiter, mach noch mehr rückgängig!
Fahren Sie fort und führen Sie git reset --hard HEAD~1
aus
Auch hier beginnt Git mit der --soft
Phase und setzt HEAD
, auf den er zeigt ( main
), auf HEAD~1
(„Commit 1“).
So weit, ist es gut.
Fahren Sie als Nächstes mit der Phase --mixed
fort und gleichen Sie den Index mit HEAD
ab. Das heißt, Git macht das Staging von 2.txt
rückgängig.
Es ist Zeit für den Schritt --hard
, bei dem Git noch weiter geht und das Arbeitsverzeichnis mit der Stufe des Index abgleicht. In diesem Fall bedeutet das, dass auch 2.txt
aus dem Arbeitsverzeichnis entfernt wird.
(**Hinweis: In diesem speziellen Fall wird die Datei nicht verfolgt, sodass sie nicht aus dem Dateisystem gelöscht wird. Dies ist jedoch nicht wirklich wichtig, um git reset
zu verstehen.)
Um also eine Änderung an Git vorzunehmen, sind drei Schritte erforderlich. Sie ändern das Arbeitsverzeichnis, den Index oder den Staging-Bereich und übertragen dann einen neuen Snapshot mit diesen Änderungen. Um diese Änderungen rückgängig zu machen:
git reset --soft
verwenden, machen wir den Commit-Schritt rückgängig.
git reset --mixed
verwenden, machen wir auch den Staging-Schritt rückgängig.
git reset --hard
verwenden, machen wir die Änderungen am Arbeitsverzeichnis rückgängig. Schreiben Sie also in einem realen Szenario „Ich liebe Git“ in eine Datei ( love.txt
), da wir alle Git lieben 😍. Machen Sie weiter, inszenieren Sie und begehen Sie auch Folgendes:
Oh, ups!
Eigentlich wollte ich nicht, dass du es begehst.
Eigentlich wollte ich, dass Sie noch ein paar liebevolle Worte in diese Datei schreiben, bevor Sie sie festschreiben.
Was kannst du tun?
Nun, eine Möglichkeit, dies zu umgehen, wäre die Verwendung von git reset --mixed HEAD~1
, wodurch sowohl die Commit- als auch die Staging-Aktionen, die Sie durchgeführt haben, effektiv rückgängig gemacht werden:
main
zeigt also erneut auf „Commit 1“ und love.txt
ist nicht mehr Teil des Index. Die Datei bleibt jedoch im Arbeitsverzeichnis. Sie können jetzt fortfahren und weitere Inhalte hinzufügen:
Machen Sie weiter, stellen Sie Ihre Datei bereit und übergeben Sie sie:
Gut gemacht 👏🏻
Sie haben diesen klaren, schönen Verlauf von „Commit 2.4“, der auf „Commit 1“ verweist.
Wir haben jetzt ein neues Tool in unserer Toolbox, git reset
💪🏻
Dieses Tool ist super, super nützlich und man kann damit fast alles erreichen. Es ist nicht immer das bequemste Tool, kann aber bei sorgfältiger Verwendung nahezu jedes Szenario zum Umschreiben des Verlaufs lösen.
Für Anfänger empfehle ich, fast immer, wenn Sie in Git rückgängig machen möchten, nur git reset
zu verwenden. Sobald Sie damit vertraut sind, ist es an der Zeit, zu anderen Tools überzugehen.
Betrachten wir einen anderen Fall.
Erstellen Sie eine neue Datei mit dem Namen new.txt
. Bühne und Commit:
Hoppla. Eigentlich ist das ein Fehler. Sie waren auf main
und ich wollte, dass Sie diesen Commit in einem Feature-Zweig erstellen. Mein schlechtes 😇
Ich möchte, dass Sie aus diesem Beitrag zwei wichtige Werkzeuge mitnehmen. Der zweite ist git reset
. Die erste und weitaus wichtigere Möglichkeit besteht darin, den aktuellen Zustand im Vergleich zu dem Zustand, in dem Sie sich befinden möchten, auf dem Whiteboard darzustellen .
Für dieses Szenario sehen der aktuelle Zustand und der gewünschte Zustand folgendermaßen aus:
Sie werden drei Änderungen bemerken:
main
deutet im aktuellen Zustand auf „Commit 3“ (das blaue) hin, im gewünschten Zustand jedoch auf „Commit 2.4“.
feature
Zweig existiert im aktuellen Zustand nicht, ist aber im gewünschten Zustand vorhanden und zeigt auf „Commit 3“.
HEAD
zeigt im aktuellen Zustand auf main
und im gewünschten Zustand auf feature
.
Wenn Sie dies zeichnen können und wissen, wie man git reset
verwendet, können Sie sich definitiv aus dieser Situation befreien.
Also noch einmal: Das Wichtigste ist, Luft zu holen und das Ganze herauszuholen.
Wie gelangen wir anhand der Zeichnung oben vom aktuellen zum gewünschten Zustand?
Natürlich gibt es verschiedene Möglichkeiten, aber ich werde für jedes Szenario nur eine Option vorstellen. Probieren Sie auch gerne andere Optionen aus.
Sie können beginnen, indem Sie git reset --soft HEAD~1
verwenden. Dies würde main
so einstellen, dass es auf den vorherigen Commit „Commit 2.4“ verweist:
Wenn Sie sich das aktuelle vs. gewünschte Diagramm noch einmal ansehen, können Sie erkennen, dass Sie einen neuen Zweig benötigen, oder? Sie können dafür git switch -c feature
oder git checkout -b feature
(die das Gleiche bewirkt) verwenden:
Dieser Befehl aktualisiert auch HEAD
so, dass es auf den neuen Zweig zeigt.
Da Sie git reset --soft
verwendet haben, haben Sie den Index nicht geändert, sodass er derzeit genau den Status hat, den Sie festschreiben möchten – wie praktisch! Sie können sich einfach auf den feature
Zweig festlegen:
Und Sie haben den gewünschten Zustand erreicht 🎉
Sind Sie bereit, Ihr Wissen auf weitere Fälle anzuwenden?
Fügen Sie einige Änderungen an love.txt
hinzu und erstellen Sie außerdem eine neue Datei mit dem Namen cool.txt
. Inszenieren Sie sie und verpflichten Sie sich:
Oh, ups, eigentlich wollte ich, dass du zwei separate Commits erstellst, einen bei jeder Änderung 🤦🏻
Möchten Sie es selbst ausprobieren?
Sie können die Commit- und Staging-Schritte rückgängig machen:
Nach diesem Befehl enthält der Index diese beiden Änderungen nicht mehr, sie befinden sich jedoch beide weiterhin in Ihrem Dateisystem. Wenn Sie also nur love.txt
bereitstellen, können Sie es separat festschreiben und dann dasselbe für cool.txt
tun:
Schön 😎
Erstellen Sie eine neue Datei ( new_file.txt
) mit etwas Text und fügen Sie etwas Text zu love.txt
hinzu. Stellen Sie beide Änderungen bereit und übernehmen Sie sie:
Ups 🙈🙈
Diesmal wollte ich also, dass es sich in einem anderen Zweig befindet, aber nicht in einem neuen Zweig, sondern in einem bereits vorhandenen Zweig.
Also was kannst du tun?
Ich gebe Ihnen einen Hinweis. Die Antwort ist wirklich kurz und wirklich einfach. Was machen wir zuerst?
Nein, nicht reset
. Wir zeichnen. Das ist das Erste, was man tun sollte, da es alles andere viel einfacher machen würde. Das ist also der aktuelle Stand:
Und der gewünschte Zustand?
Wie gelangt man vom aktuellen zum gewünschten Zustand, was wäre am einfachsten?
Eine Möglichkeit wäre also git reset
wie zuvor zu verwenden, aber ich möchte, dass Sie auch eine andere Möglichkeit ausprobieren.
Verschieben Sie zunächst HEAD
so, dass es auf den existing
Zweig zeigt:
Intuitiv möchten Sie die im blauen Commit eingeführten Änderungen übernehmen und diese Änderungen („Kopieren und Einfügen“) auf den existing
Zweig anwenden. Und Git hat genau dafür ein Tool.
Um Git aufzufordern, die zwischen diesem Commit und seinem übergeordneten Commit eingeführten Änderungen zu übernehmen und diese Änderungen einfach auf den aktiven Zweig anzuwenden, können Sie git cherry-pick
verwenden. Dieser Befehl übernimmt die in der angegebenen Revision eingeführten Änderungen und wendet sie auf das aktive Commit an.
Außerdem wird ein neues Commit-Objekt erstellt und der aktive Zweig aktualisiert, sodass er auf dieses neue Objekt verweist.
Im obigen Beispiel habe ich die SHA-1-Kennung des erstellten Commits angegeben, Sie können aber auch git cherry-pick main
verwenden, da der Commit, dessen Änderungen wir anwenden, derjenige ist, auf den main
verweist.
Wir möchten jedoch nicht, dass diese Änderungen im main
vorhanden sind. git cherry-pick
hat die Änderungen nur auf den existing
Zweig angewendet. Wie kann man sie aus main
entfernen?
Eine Möglichkeit wäre, zurück zu main
zu switch
und dann git reset --hard HEAD~1
zu verwenden:
Du hast es geschafft! 💪🏻
Beachten Sie, dass git cherry-pick
tatsächlich die Differenz zwischen dem angegebenen Commit und seinem übergeordneten Commit berechnet und diese dann auf den aktiven Commit anwendet. Das bedeutet, dass Git diese Änderungen manchmal nicht anwenden kann, da es zu einem Konflikt kommen kann, aber das ist ein Thema für einen anderen Beitrag.
Beachten Sie außerdem, dass Sie Git bitten können, die in jedem Commit eingeführten Änderungen cherry-pick
, nicht nur in Commits, auf die von einem Zweig verwiesen wird.
Wir haben ein neues Tool erworben, also haben wir sowohl git reset
als auch git cherry-pick
in der Tasche.
Okay, also ein anderer Tag, ein anderes Repo, ein anderes Problem.
Erstellen Sie ein Commit:
Und push
es auf den Remote-Server:
Ähm, ups 😓…
Mir ist gerade etwas aufgefallen. Da liegt ein Tippfehler vor. Ich habe This is more tezt
anstelle von This is more text
geschrieben. Hoppla. Was ist nun das große Problem? Ich habe ed push
, was bedeutet, dass jemand anderes diese Änderungen möglicherweise bereits pull
hat.
Wenn ich diese Änderungen überschreibe, indem ich git reset
verwende, wie wir es bisher getan haben, werden wir unterschiedliche Historien haben, und die Hölle könnte losbrechen. Sie können Ihre eigene Kopie des Repos so oft umschreiben, wie Sie möchten, bis Sie sie push
.
Sobald Sie die Änderung push
, müssen Sie sehr sicher sein, dass niemand anderes diese Änderungen abgerufen hat, wenn Sie den Verlauf neu schreiben möchten.
Alternativ können Sie ein anderes Tool namens git revert
verwenden. Dieser Befehl nimmt den Commit, den Sie ihm zur Verfügung stellen, und berechnet den Unterschied zum übergeordneten Commit, genau wie git cherry-pick
, berechnet dieses Mal jedoch die umgekehrten Änderungen.
Wenn Sie also im angegebenen Commit eine Zeile hinzugefügt haben, würde der umgekehrte Vorgang die Zeile löschen und umgekehrt.
git revert
hat ein neues Commit-Objekt erstellt, was bedeutet, dass es eine Ergänzung zum Verlauf ist. Durch die Verwendung von git revert
haben Sie den Verlauf nicht neu geschrieben. Sie haben Ihren Fehler in der Vergangenheit zugegeben, und dieser Commit ist ein Eingeständnis, dass Sie einen Fehler gemacht und ihn nun behoben haben.
Manche würden sagen, es sei der ausgereiftere Weg. Einige würden sagen, dass der Verlauf nicht so sauber ist, wie wenn Sie git reset
verwenden würden, um den vorherigen Commit neu zu schreiben. Aber so lässt sich vermeiden, dass die Geschichte neu geschrieben wird.
Sie können den Tippfehler jetzt beheben und erneut festschreiben:
Ihr Werkzeugkasten ist jetzt mit einem neuen, glänzenden Werkzeug geladen. revert
:
Erledigen Sie Ihre Arbeit, schreiben Sie Code und fügen Sie ihn zu love.txt
hinzu. Führen Sie diese Änderung durch und übernehmen Sie sie:
Ich habe das Gleiche auf meinem Computer gemacht und mit der Up
auf meiner Tastatur zu den vorherigen Befehlen zurückgeblättert. Dann habe ich Enter
gedrückt und … Wow.
Hoppla.
Habe ich gerade git reset --hard
verwendet? 😨
Was ist eigentlich passiert? Git hat den Zeiger auf HEAD~1
verschoben, sodass der letzte Commit mit all meiner wertvollen Arbeit aus dem aktuellen Verlauf nicht erreichbar ist. Git hat auch alle Änderungen aus dem Staging-Bereich entfernt und dann das Arbeitsverzeichnis an den Status des Staging-Bereichs angepasst.
Das heißt, alles passt zu diesem Zustand, in dem meine Arbeit … weg ist.
Zeit zum Ausflippen. Ausrasten.
Aber gibt es wirklich einen Grund auszuflippen? Nicht wirklich... Wir sind entspannte Menschen. Was machen wir? Nun, ist der Commit intuitiv wirklich, wirklich weg? Nein Warum nicht? Es existiert immer noch in der internen Datenbank von Git.
Wenn ich nur wüsste, wo das ist, wüsste ich den SHA-1-Wert, der diesen Commit identifiziert, und wir könnten ihn wiederherstellen. Ich könnte das Rückgängigmachen sogar rückgängig machen und zu diesem Commit reset
.
Das Einzige, was ich hier also wirklich brauche, ist der SHA-1 des „gelöschten“ Commits.
Die Frage ist also, wie finde ich es? Wäre git log
nützlich?
Nicht wirklich. git log
würde zu HEAD
gehen, was auf main
verweist, was auf den übergeordneten Commit des gesuchten Commits verweist. Dann würde git log
Daten über die übergeordnete Kette zurückverfolgen, was den Commit nicht mit meiner wertvollen Arbeit einschließt.
Zum Glück haben die sehr klugen Leute, die Git erstellt haben, auch einen Backup-Plan für uns erstellt, und dieser heißt reflog
.
Während Sie mit Git arbeiten, fügt Git jedes Mal, wenn Sie HEAD
ändern, was Sie mit git reset
tun können, aber auch mit anderen Befehlen wie git switch
oder git checkout
, einen Eintrag zum reflog
hinzu.
Wir haben unser Engagement gefunden! Es ist das, das mit 0fb929e
beginnt.
Wir können es auch anhand seines „Spitznamens“ identifizieren – HEAD@{1}
. So wie Git beispielsweise HEAD~1
verwendet, um zum ersten übergeordneten Element von HEAD
zu gelangen, und HEAD~2
, um auf das zweite übergeordnete Element von HEAD
zu verweisen, usw., verwendet Git HEAD@{1}
, um auf das erste Reflog-übergeordnete Element von HEAD
zu verweisen. wo HEAD
im vorherigen Schritt gezeigt hat.
Wir können git rev-parse
auch bitten, uns seinen Wert zu zeigen:
Eine andere Möglichkeit, das reflog
anzuzeigen, ist die Verwendung von git log -g
, wodurch git log
aufgefordert wird, das reflog
tatsächlich zu berücksichtigen:
Wir sehen oben, dass reflog
ebenso wie HEAD
auf main
verweist, was auf „Commit 2“ verweist. Aber das übergeordnete Element dieses Eintrags im reflog
verweist auf „Commit 3“.
Um also zu „Commit 3“ zurückzukehren, können Sie einfach git reset --hard HEAD@{1}
(oder den SHA-1-Wert von „Commit 3“) verwenden:
Und jetzt, wenn wir git log
:
Wir haben den Tag gerettet! 🎉👏🏻
Was würde passieren, wenn ich diesen Befehl erneut verwenden würde? Und git commit --reset HEAD@{1}
ausgeführt? Git würde HEAD
auf die Stelle setzen, auf HEAD
vor dem letzten reset
zeigte, also auf „Commit 2“. Wir können den ganzen Tag weitermachen:
Wenn Sie sich jetzt unsere Toolbox ansehen, ist sie voller Tools, die Ihnen bei der Lösung vieler Fälle helfen können, in denen in Git etwas schief geht:
Mit diesen Tools verstehen Sie jetzt besser, wie Git funktioniert. Es gibt weitere Tools, mit denen Sie den Verlauf gezielt umschreiben können ( git rebase
), aber Sie haben in diesem Beitrag bereits viel gelernt. In zukünftigen Beiträgen werde ich mich auch mit git rebase
befassen.
Das wichtigste Werkzeug, noch wichtiger als die fünf in dieser Toolbox aufgeführten Werkzeuge, ist das Whiteboarden der aktuellen Situation im Vergleich zur gewünschten. Vertrauen Sie mir, dadurch wird jede Situation weniger entmutigend und die Lösung klarer.
Ich habe auch einen Live-Vortrag über den Inhalt dieses Beitrags gehalten. Wenn Sie ein Video bevorzugen (oder es neben der Lektüre ansehen möchten), können Sie es finden
Allgemein,
Omer hat einen MA in Linguistik von der Universität Tel Aviv und ist der Schöpfer des
Erstveröffentlichung hier