git reflog
Deze pagina bevat een gedetailleerde beschrijving van de opdracht git reflog
. Git houdt updates van het uiteinde van branches bij met behulp van een mechanisme dat referentielogs of 'reflogs' wordt genoemd. Veel Git-opdrachten accepteren een parameter voor het specificeren van een referentie of 'ref', wat een pointer naar een commit is. Gangbare voorbeelden zijn:
Reflogs houden bij wanneer Git-refs zijn bijgewerkt in de lokale repository. Naast reflogs voor branchuiteinden wordt er een speciale reflog bijgehouden voor de Git stash. Reflogs worden opgeslagen in mappen onder de map .git
van de lokale repository. De git reflog
-mappen zijn te vinden in .git/logs/refs/heads/.
, .git/logs/HEAD
en ook in .git/logs/refs/stash
als de git stash
is gebruikt in de repo.
We hebben git reflog
op hoog niveau besproken op de pagina Geschiedenis herschrijven. Dit document behandelt: uitgebreide configuratieopties voor git reflog
, veelvoorkomende usecases en valkuilen van git reflog
, hoe je wijzigingen ongedaan kunt maken met git reflog
en meer.
Basisgebruik
De meest elementaire usecase van Reflog is het aanroepen van:
git reflog
Dit is in wezen een snelkoppeling die gelijk is aan:
git reflog show HEAD
Hiermee wordt de HEAD
-reflog weergeven. Je zou ongeveer de volgende output moeten zien:
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 editor
Ga naar de pagina Geschiedenis herschrijven voor nog een voorbeeld van veelvoorkomende gebruik van reflog.
Reflog-referenties
Met git reflog
wordt standaard de reflog van de HEAD
-ref weergegeven. HEAD
is een symbolische verwijzing naar de momenteel actieve branch. Reflogs zijn ook beschikbaar voor andere refs. De syntaxis voor toegang tot een git ref is name@{qualifier}
. Naast HEAD
-refs kunnen ook andere branches, tags, remotes en de Git-stash worden geraadpleegd.
Je kunt een volledige reflog van alle refs verkrijgen door de volgende opdracht uit te voeren:
git reflog show --all
Om de reflog voor een specifieke branch te zien, geef je de naam van die branch door aan git reflog show
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 docs
Als je dit voorbeeld uitvoert, krijg je een reflog voor de branch otherbranch
. In het volgende voorbeeld wordt ervan uitgegaan dat je eerder enkele wijzigingen hebt opgeslagen met de opdracht git stash
.
git reflog stash 0d44de3 stash@{0}: WIP on git_reflog: c492574 flesh out intro
Dit levert een reflog op voor de Git-stash. De geretourneerde ref pointers kunnen worden doorgegeven aan andere Git-opdrachten:
git diff stash@{0} otherbranch@{0}
Wanneer deze voorbeeldcode wordt uitgevoerd, geeft deze de diff-uitvoer van Git weer, waarbij de stash@{0}
-wijzigingen worden vergeleken met de otherbranch@{0}
-ref.
Getimede reflogs
Aan elk reflog-item is een tijdstempel gekoppeld. Deze tijdstempels kunnen worden gebruikt als qualifier
-token voor de Git ref-pointersyntaxis. Hiermee kunnen Git-reflogs op tijd worden gefilterd. Hieronder volgen een paar voorbeelden van beschikbare tijdkwalificaties:
1.minute.ago
1.hour.ago
1.day.ago
Gisteren
1.week.ago
1.month.ago
1.year.ago
2011-05-17.09:00:00
Tijdrukkwalificaties kunnen gecombineerd worden (bijv. 1.day.2.hours.ago
), Daarnaast worden meervoudige vormen geaccepteerd (bijv. 5.minutes.ago
).
Tijdkwalificatiereferenties kunnen worden doorgegeven aan andere Git-opdrachten.
git diff main@{0} main@{1.day.ago}
In dit voorbeeld wordt een diff gemaakt van de huidige main-branch ten opzichte van die van 1 dag geleden. Dit voorbeeld is erg nuttig als je wilt weten welke veranderingen er binnen een bepaald tijdsbestek zijn opgetreden.
Subopdrachten en configuratieopties
git reflog
accepteert enkele aanvullende argumenten die als subopdrachten worden beschouwd.
Show - git reflog show
show
wordt standaard impliciet doorgegeven. Bijvoorbeeld de opdracht:
git reflog main@{0}
is gelijk aan de opdracht:
git reflog show main@{0}
Bovendien is git reflog show
een alias voor git log -g --abbrev-commit --pretty=oneline
. Executing git reflog show
geeft het log weer voor de doorgegeven
Expire - git reflog expire
De subopdracht expire ruimt oude of onbereikbare reflog-vermeldingen op. De subopdracht expire
kan leiden tot gegevensverlies. Deze subopdracht wordt doorgaans niet gebruikt door eindgebruikers, maar intern door Git. Wanneer je de optie -n
of --dry-run
doorgeeft aan git reflog expire
, wordt er een 'dry run' uitgevoerd die in de output aangeeft welke reflog-vermeldingen zijn gemarkeerd om te worden opgeschoond, zonder ze daadwerkelijk op te schonen.
De vervaldatum van de reflog is standaard ingesteld op 90 dagen. Een vervaltijd kan worden opgegeven door een opdrachtregelargument --expire=time
door te geven aan git reflog expire
of door de Git-configuratienaam in te stellen op gc.reflogExpire
.
Delete - git reflog delete
De subopdracht delete
spreekt voor zich en verwijdert een doorgegeven element in een reflog-vermelding. Net als bij de expire
kunnen met delete
gegevens verloren gaan en wordt deze opdracht niet vaak aangeroepen door eindgebruikers.
Verloren commits herstellen
Git verliest eigenlijk nooit iets, zelfs niet bij operaties om de geschiedenis te herschrijven, zoals rebasen of commit-wijzigingen. Laten we voor het volgende voorbeeld aannemen dat we een aantal nieuwe wijzigingen hebben aangebracht in onze repo. Onze git-log --pretty=oneline
ziet er als volgt uit:
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 docs
Vervolgens committen we die veranderingen en voeren we het volgende uit:
#make changes to HEAD git commit -am "some WIP changes"
Met de toevoeging van de nieuwe commit ziet het log er nu zo uit:
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 docs
Op dit punt voeren we een interactieve rebase uit tegen de main-branch door de volgende opdracht uit te voeren ...
git rebase -i origin/main
Tijdens de rebase markeren we commits voor squash met de rebase-subopdracht s
. Tijdens de rebase squashen we een paar commits in de meest recente commit 'some WIP changes'.
Omdat we commits hebben gesquasht, ziet de git log
-output er nu als volgt uit:
40dhsoi37656e19d4e4f1a9b419f57850ch87dah987698hs some WIP changes 35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs
Als we nu git log
bekijken, blijkt dat we niet langer de commits hebben die gemarkeerd waren voor squashing. Wat als we iets willen doen met een van de gesquashte commits? Misschien om de wijzigingen uit de geschiedenis te verwijderen? Dit is een kans om gebruik te maken van de reflog.
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 changes
We kunnen zien dat er reflog-vermeldingen zijn voor het begin en einde van de rebase
, en daarvoor is onze 'some WIP changes' uitgevoerd. We kunnen de reflog-referentie doorgeven aan git reset
en resetten naar een commit vóór de rebase.
git reset HEAD@{2}
Als je deze reset-opdracht uitvoert, wordt HEAD
naar de commit verplaatst waar 'some WIP changes' is toegevoegd, waardoor in feite de andere gesquashte commits worden hersteld.
Samenvatting
In deze tutorial hebben we de opdracht git reflog
besproken. Enkele belangrijke punten die aan bod kwamen waren:
- reflog voor specifieke branches weergeven
- Een Git-rebase ongedaan maken met de reflog
- Op tijd gebaseerde reflog-vermeldingen specificeren en weergeven
We hebben kort vermeld dat git reflog
kan worden gebruikt met andere git-opdrachten zoals git checkout, git reset en git merge. Meer informatie vind je op hun respectievelijke pagina's. Voor een verdere bespreking van refs en de reflog, vind je hier meer informatie.