git reflog
In diesem Artikel wird der Befehl git reflog im Detail erläutert. Git verfolgt die Updates an den Branch-Spitzen mit einem Mechanismus namens Reflog (kurz für reference log – Referenzprotokoll). Viele Git-Befehle akzeptieren einen Parameter zur Bestimmung einer Referenz oder "Ref" als Pointer zu einem Commit. Einige gebräuchliche Beispiele:
git checkoutgit resetgit merge <ref>
Reflogs verfolgen, wann Git-Refs im lokalen Repository aktualisiert wurden. Neben den Reflogs der Branch-Spitzen wird ein spezieller Reflog für den Git Stash gepflegt. Reflogs werden in Verzeichnissen unter dem .git-Verzeichnis des lokalen Repositorys gespeichert. git reflog-Verzeichnisse befinden sich unter .git/logs/refs/heads/., .git/logs/HEAD und .git/logs/refs/stash, wenn git stash für das Repository verwendet wurde.
Wir haben git reflog auf der Seite Umarbeiten von Verläufen bereits oberflächlich angesprochen. In diesem Artikel behandeln wir folgende Themen: die erweiterten Konfigurationsoptionen von git reflog, häufige Anwendungsfälle und Fallstricke von git reflog, das Rückgängigmachen von Änderungen mit git reflog und mehr.
Grundlegende Nutzung
Der einfachste Reflog-Use Case:
git reflogDies ist im Prinzip eine Abkürzung von:
git reflog show HEADDies gibt den HEAD-Reflog zurück. Die Ausgabe sieht ungefähr so aus:
eff544f HEAD@{0}: commit: migrate existing content
bf871fd HEAD@{1}: commit: Add Git Reflog outline
9a4491f HEAD@{2}: checkout: moving from main to git_reflog
9a4491f HEAD@{3}: checkout: moving from Git_Config to main
39b159a HEAD@{4}: commit: expand on git context
9b3aa71 HEAD@{5}: commit: more color clarification
f34388b HEAD@{6}: commit: expand on color support
9962aed HEAD@{7}: commit: a git editor -> the Git editorAuf der Seite Umarbeiten von Verläufen findest du ein weiteres Beispiel für eine gebräuchliche Verwendung von "git reflog".
Reflog-Referenzen
In den Standardeinstellungen gibt git reflog das Reflog der HEAD-Referenz zurück. HEAD ist eine symbolische Referenz zum aktuell aktiven Branch. Reflogs sind auch für andere Referenzen verfügbar. Die Syntax für den Zugriff auf eine Git-Referenz lautet name@{qualifier}. Neben den HEAD-Refs können auch andere Branches, Tags, Remotes und der Git Stash referenziert werden.
Wenn du folgenden Befehl ausführst, erhältst du einen vollständigen Reflog aller Referenzen:
git reflog show --allZur Anzeige des Reflogs für einen bestimmten Branch fügst du git reflog show den Branch-Namen hinzu.
In Bitbucket wird die Seite Create a new repository (Neues Repository erstellen) angezeigt. Verschaffe dir zunächst einen Überblick über die Inhalte im Dialogfeld. Mit Ausnahme des Repository-Typs kannst du alle Eingaben auf dieser Seite später wieder ändern.
git reflog show otherbranch
9a4491f otherbranch@{0}: commit: seperate articles into branch PRs
35aee4a otherbranch{1}: commit (initial): initial commit add git-init and setting-up-a-repo docsDas Ausführen dieses Beispiels gibt einen Reflog für den Branch otherbranch zurück. Im folgenden Beispiel nehmen wir an, du hast zuvor einige Änderungen mit dem Befehl git stash beiseitegelegt.
git reflog stash
0d44de3 stash@{0}: WIP on git_reflog: c492574 flesh out introDies gibt ein Reflog für den Git Stash zurück. Die angezeigten Referenz-Pointers können an andere Git-Befehle angefügt werden:
git diff stash@{0} otherbranch@{0}Wenn dieser Beispielcode ausgeführt wird, wird eine Git diff-Ausgabe angezeigt, in der die stash@{0}-Änderungen mit der otherbranch@{0}-Referenz verglichen werden.
Reflogs für einen bestimmten Zeitpunkt
Jedes Reflog ist mit einer Zeitmarke versehen. Diese Zeitmarken können in einer Git Referenz-Pointer-Syntax als qualifier-Token genutzt werden. Auf diese Weise können Git-Reflogs nach Zeitpunkten gefiltert werden. Im Folgenden siehst du einige Beispiele verfügbarer Zeit-Qualifier:
1.minute.ago1.hour.ago1.day.agoyesterday1.week.ago1.month.ago1.year.ago2011-05-17.09:00:00
Zeit-Qualifier können kombiniert werden (z. B. 1.day.2.hours.ago) und auch Pluralformen werden akzeptiert (z. B. 5.minutes.ago).
Zeit-Qualifier können an andere Git-Befehle angefügt werden.
git diff main@{0} main@{1.day.ago}In diesem Beispiel wird der aktuelle Main-Branch mit dem Main von vor einem Tag verglichen. Dieses Beispiel ist äußerst hilfreich, wenn du wissen möchtest, was sich innerhalb eines bestimmten Zeitraums geändert hat.
Unterbefehle und Konfigurationsoptionen
git reflog akzeptiert einige zusätzliche Argumente, die als Unterbefehle betrachtet werden.
Show -git reflog show
show wird standardmäßig impliziert. Beispielsweise ist der Befehl:
git reflog main@{0}gleichbedeutend mit dem Befehl:
git reflog show main@{0}Außerdem ist git reflog show ein Alias für git log -g --abbrev-commit --pretty=oneline. Mit git reflog show <refid> wird das Protokoll für die angegebene <refid> angezeigt.
Expire -git reflog expire
Der Unterbefehl "expire" bereinigt alte oder unerreichbare Reflog-Einträge. Doch beim expire-Unterbefehl können potenziell Daten verloren gehen. Deshalb wird dieser Unterbefehl normalerweise nicht von Endbenutzern, sondern von Git intern verwendet. Durch das Hinzufügen der Option -n oder --dry-run zu git reflog expire wird ein "Probelauf" durchgeführt, der zurückgibt, welche Reflog-Einträge zum Pruning markiert wurden, ohne sie tatsächlich zu löschen.
Standardmäßig ist das Reflog-Ablaufdatum auf 90 Tage gesetzt. Das Ablaufdatum kann individuell festgelegt werden, indem der Zusatz --expire=time an git reflog expire angefügt wird oder indem ein Git Konfigurationsname für gc.reflogExpire eingerichtet wird.
Delete -git reflog delete
Der Unterbefehl delete erklärt sich eigentlich von selbst: Der angegebene Reflog-Eintrag wird gelöscht. Wie expire kann auch delete potenziell zu Datenverlusten führen und wird normalerweise nicht von Endbenutzern verwendet.
Wiederherstellen verlorener Commits
In Git geht nichts wirklich verloren, nicht einmal beim Umarbeiten eines Verlaufs mit Vorgängen wie Rebasing oder Commit-Änderungen. Im nächsten Beispiel nehmen wir an, wir haben Änderungen an unserem Repository vorgenommen. Unsere Ausgabe für git log --pretty=oneline sieht folgendermaßen aus:
338fbcb41de10f7f2e54095f5649426cb4bf2458 extended content
1e63ceab309da94256db8fb1f35b1678fb74abd4 bunch of content
c49257493a95185997c87e0bc3a9481715270086 flesh out intro
eff544f986d270d7f97c77618314a06f024c7916 migrate existing content
bf871fd762d8ef2e146d7f0226e81a92f91975ad Add Git Reflog outline
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docsWir committen diese Änderungen und führen Folgendes aus:
#make changes to HEAD
git commit -am "some WIP changes"Nachdem der neue Commit hinzugekommen ist, sieht das Protokoll folgendermaßen aus:
$ git clone
https://emmap1@bitbucket.org/emmap1/bitbucketstationlocations.git
Cloning into 'bitbucketspacestation'...
fatal: could not read
Password for 'https://emmap1@bitbucket.org': No such file or directoryWenn du diese Fehlermeldung erhältst, gib Folgendes in die Befehlszeile ein:
37656e19d4e4f1a9b419f57850c8f1974f871b07 some WIP changes
338fbcb41de10f7f2e54095f5649426cb4bf2458 extended content
1e63ceab309da94256db8fb1f35b1678fb74abd4 bunch of content
c49257493a95185997c87e0bc3a9481715270086 flesh out intro
eff544f986d270d7f97c77618314a06f024c7916 migrate existing content
bf871fd762d8ef2e146d7f0226e81a92f91975ad Add Git Reflog outline
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docsNun führen wir ein interaktives Rebasing mit dem Main-Branch durch. Dies geschieht mit dem folgenden Befehl:
git rebase -i origin/mainWährend des Rebasings markieren wir mit dem Rebase-Unterbefehl s Commits für einen Squash. Außerdem squashen wir einige Commits in den neuesten "some WIP changes"-Commit.
Da wir Commits gesquasht haben sieht die Ausgabe von git log nun folgendermaßen aus:
40dhsoi37656e19d4e4f1a9b419f57850ch87dah987698hs some WIP changes
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docsWenn wir uns git log jetzt ansehen, sieht es so aus, als ob keine weiteren Commit für einen Squash markiert sind. Wie gehen wir vor, wenn wir eine Aktion für einen der gesquashten Commits durchführen möchten? Vielleicht sollen seine Änderungen aus dem Verlauf entfernt werden? Hierzu kann das Reflog genutzt werden.
git reflog
37656e1 HEAD@{0}: rebase -i (finish): returning to refs/heads/git_reflog
37656e1 HEAD@{1}: rebase -i (start): checkout origin/main
37656e1 HEAD@{2}: commit: some WIP changesWir sehen hier, dass es Reflog-Einträge für den Beginn und das Ende für rebase gibt, und vor diesen steht unser "some WIP changes"-Commit. Wir können die Reflog-Referenz an git reset anfügen und auf einen Commit zurücksetzen, der vor dem Rebasing vorhanden war.
git reset HEAD@{2}Das Ausführen von "git reset" verschiebt HEAD zu dem Commit, dem der "some WIP changes"-Commit hinzugefügt wurde, und stellt im Wesentlichen die anderen gesquashten Commits wieder her.
Zusammenfassung
In diesem Tutorial haben wir den Befehl git reflog behandelt. Dabei wurden insbesondere die folgenden Themen besprochen:
Ansehen des Reflogs für bestimmte Branches
Rückgängigmachen einer Git Rebase mithilfe des Reflogs
Angeben und Ansehen von Reflog-Einträgen für einen bestimmten Zeitpunkt
Wir haben kurz erwähnt, dass git reflog mit anderen Befehlen wie git checkout, git reset und git merge kombiniert werden kann. Hierzu erfährst du auf den jeweiligen Seiten mehr. Weitere Informationen zu Referenzen und zum Reflog findest du hier.
Für dich empfohlen
Bitbucket-Blog
DevOps-Lernpfad
Weitere Informationen zu Git
Weitere Git-Anleitungen und Ressourcen findest du in diesem Hub.