• Home
  • |
  • Blog
  • |
  • Git Tutorial #5 – Git checkout und HEAD

Git Tutorial #5 – Git checkout und HEAD

Zuletzt aktualisiert: September 19, 2024

Im heutigen Artikel wirst du lernen, wie man mithilfe von git checkout von einem Commit zum anderen wechseln kann. Auf diese Weise ist es beispielsweise möglich, den Zustand einer älteren Version wiederherzustellen. So fungiert Git als eine Art Zeitmaschine, die sich als sehr nützlich erweisen kann, wie du in den folgenden Absätzen sehen wirst. 

Inhaltsverzeichnis

1. Der Head-Pointer

Um direkt starten zu können, habe ich bereits die Git Bash geöffnet und bin in den Repository Ordner navigiert. Mit „git log“ sehen wir uns nun noch mal die Historie an, um zu prüfen, welche Commits wir bereits erstellt haben.

Auf der folgenden Abbildung sehen wir den zweiten Commit „Korrektur von Rechtschreibfehler“ sowie den ersten Commit „Erste Version von unserem Website Projekt“.

Außerdem ist oben die Zeile „HEAD -> main“ zu erkennen. Es handelt sich dabei um einen Head-Pointer, den du dir wie einen Zeiger vorstellen kannst, der immer auf den aktuell ausgewählten Commit oder Branch zeigt. Wir arbeiten also immer dort, worauf der Head-Pointer gerade zeigt.

Der Head-Pointer zeigt auf den Main Branch

Wenn wir auf den ersten Commit zurückgehen, bewegt sich der Head-Pointer auch mit auf diesen Commit. Wir arbeiten dann also mit diesem.

Wichtig: Man kann nicht nur auf Commits zeigen, sondern auch auf Branches, wie wir hier sehen.

Der Head-Pointer zeigt auf den Main-Branch. Fügen wir an dieser Stelle einen Commit hinzu, bewegt sich der Main-Branch nach vorne. Wie das aussieht, werde ich dir gleich noch grafisch zeigen. Der Head-Pointer fährt also mit dem Main-Branch mit.

2. Der Befehl git checkout

Nun werden wir uns ansehen, wie wir mithilfe des Befehls git checkout zu einem Commit zurückspringen bzw. den Head-Pointer auf einen beliebigen Commit oder Branch bewegen können.

Wie funktioniert das? Zunächst brauchen wir dafür den Hash-Wert des Commits, zu dem wir uns bewegen möchten. Der Commit „Erste Version von unserem Website Projekt“ hat beispielsweise den folgenden Hash-Wert:

Der erste Git Commit hat diesen Hash-Wert

Wir selektieren also diesen Wert, machen einen Rechtsklick und klicken dann auf „copy“. Anschließend schreiben wir „git checkout“ und fügen dahinter mit einem Rechtsklick und „paste“ den Hash-Wert ein. Drücken wir jetzt auf Enter, dann bewegen wir den Head-Pointer auf genau diesen Commit.

Mit git checkout und dem Hash-Wert bewegen wir den Head-Pointer auf den Commit

3. Die Warnung: "You are in detached HEAD state"

Jetzt ist erst mal etwas Beunruhigendes passiert: Wir haben die Warnung „You are in detached HEAD state“ erhalten. Was im ersten Moment dramatisch klingt, ist letztendlich aber nichts, worüber wir uns große Sorgen machen müssen. Wir befinden uns immer dann im „detached HEAD state“, wenn wir mit unserem Head-Pointer nicht auf einen Branch zeigen, sondern auf einen einzelnen Commit.

Was es damit auf sich hat, werde ich dir in der folgenden Grafik zeigen. Du hast eben bereits gelernt, dass der Head-Pointer wie ein Zeiger funktioniert, der immer auf den aktuell ausgewählten Branch oder Commit zeigt. Im Beispiel ist genau das zu erkennen.

Der Head-Pointer zeigt auf den aktuell ausgewählten Branch

Wir haben einen Main Branch, wobei es sich um ein kleines Projekt handelt und darüber hinaus bereits drei Commits. Das sind Commit A, B und C. Jetzt können wir zu diesem Branch noch einen weiteren Commit hinzufügen. Wenn der Head-Pointer auch auf den Branch Main zeigt, passiert dann Folgendes:

Der neue Commit wird erstellt und der Branch, auf den wir gerade zeigen, bewegt sich ein Stück nach vorne. Somit liegt der neue Commit hinter dem Branch.

Der neue Git Commit wird erstellt und der Branch bewegt sich nach vorne

4. Einen neuen Branch erstellen

Wir können natürlich auch noch einen weiteren Branch erstellen, in welchem wir ein neues Feature entwickeln. Durch die Entwicklung in einem eigenen Branch stellen wir sicher, dass der Prozess keine Auswirkungen auf unseren Main Branch hat.

Git checkout: wir erstellen den Branch Feature

Anschließend können wir auch dort wieder einen Commit anlegen. Weil der Head-Pointer bereits auf unseren Branch Feature gezeigt hat, wurde der Commit zu diesem hinzugefügt. Das heißt: Der Commit wurde vor dem Branch Feature erstellt, welcher sich wiederum ein Stück nach vorne bewegt hat.

Der Commit wurde vor dem Branch Feature erstellt

Wie du siehst, bewegt sich der Branch, auf den der Head-Pointer zeigt, bei jedem Commit ein Stück nach vorne. Der Commit gehört dann zu diesem Entwicklungszweig (Branch).

Man kann mit dem Head-Pointer allerdings nicht nur auf Branches zeigen, sondern auch auf einzelne Commits. Damit haben wir zum Beispiel die Möglichkeit, auf den Commit C zu zeigen. Das lässt sich umsetzen, indem wir Git Checkout und den Hash-Wert dieses Commits aufrufen.

5. Detached HEAD state: Was passiert hier?

Wenn wir mit dem Head-Pointer nicht auf einen Branch, sondern stattdessen auf einen einzelnen Commit zeigen, befinden wir uns im detached Head State.

git checkout: wir befinden uns im detached head state
Wichtig: Dadurch wird die zu Beginn erwähnte Warnung hervorgerufen.

Denn: Beim Zeigen auf einen einzelnen Commit besteht noch immer die Möglichkeit, weitere Commits zu erstellen. Diese weiteren Commits sind dann „kopflos“ und damit nicht Teil eines bestimmten Branches. Würden wir also auf dem Commit C einen weiteren Commit setzen, sähe das Ganze folgendermaßen aus:

Auf dem Commit C wird ein weiterer Commit gesetzt

6. Warum der detached HEAD state problematisch sein kann

Dann gäbe es den neuen Commit F, welcher zu keinem Branch gehört. Das bedeutet: Wenn wir nun bei einem beliebigen anderen Branch arbeiten und wieder zurück zu Commit F möchten, wird es schwierig, diesen zu finden. Schließlich sind die Branches nicht lediglich dazu da, Entwicklungszweige zu erstellen, sondern dienen ebenso als Orientierungspunkte.

Wenn wir also Commits erstellen, die zu keinem Branch gehören, wird das Ganze etwas chaotisch. Aus diesem Grund erhalten wir den Hinweis, dass der HEAD gerade detached, also frei stehend ist, was immer dann passiert, wenn wir mit dem Head-Pointer auf einen einzelnen Commit zeigen, anstatt auf einen Branch.

So viel zum Thema Head-Pointer.

7. Den Projektstatus in der Git Bash nachvollziehen

Zurück in der Git Bash sehen wir noch immer die Nachricht, dass wir uns im Detached Head Space befinden, da wir zum ersten Commit gewechselt sind.

Wenn wir jetzt noch einmal „git log“ eingeben, sehen wir den Log bis zu dem Zeitpunkt in unserem Projekt, an dem wir uns gerade befinden.

Darin wird nur der Commit angezeigt, auf den der HEAD zeigt. Außerdem sehen wir, dass dort nicht wieder „HEAD“ mit einem Pfeil auf einen Branch-Namen steht, sondern lediglich „HEAD“. Er zeigt also nur auf den Commit.

Der Head zeigt nur auf den Git Commit

8. Mit git checkout zurück zum Main Branch steuern

An dieser Stelle werden wir uns nun wieder zurück zum aktuellen Stand unseres Projekts bewegen, nämlich zum Main Branch. Dazu schreiben wir zunächst einmal „git checkout“. Da wir jetzt aber nicht zu einem Commit springen möchten, sondern zum Main Branch, benötigen wir keinen Hash-Wert. Stattdessen genügt der Name des Branches, zu dem wir möchten. Wir geben also „git checkout main“ ein:

Mit git checkout main navigieren wir zurück zum Main Branch

Daraufhin befinden wir uns auch schon wieder an diesem Punkt. Wenn wir nun „git log“ in die Konsole eingeben, sehen wir beide Commits und darüber hinaus, dass der Head auf den Branch Main zeigt:

git checkout: Wir sehen wieder beide Commits und dass der Head auf den Main Branch zeigt

An dieser Stelle möchte ich dir zeigen, dass es einen Unterschied macht, wo wir uns im Projekt mit dem Head-Pointer befinden. Werfen wir einen genaueren Blick auf unseren Projektordner, sehen wir die Datei index.html. Öffnen wir diese, steht darin der Satz „Das hier ist meine eigene Website“. Wir sind gerade auf dem aktuellen Commit, also auf unserem Main Branch.

Springen wir nun allerdings nochmal zurück zu unserem ersten Commit, indem wir „git checkout“ und dessen Hash-Wert eingeben, dann befinden wir uns mit dem Head-Pointer wieder auf der ersten Version unseres Projekts. Beim erneuten Laden der Website taucht auch der Rechtschreibfehler der ersten Version wieder auf.

Der Rechtschreibfehler ist nun wieder sichtbar

Der Ort, an dem wir uns befinden, macht also tatsächlich einen Unterschied.

Wie du siehst, können wir mithilfe von git checkout den Stand unseres Projekts wieder zu einer alten Version zurücksetzen lassen, zur aktuellen Version springen, in einen anderen Branch wechseln, usw.

Du hast in diesem Beitrag also gelernt, wie man den git checkout Befehl verwendet und welche Rolle der Head-Pointer dabei spielt.