0%

Dingen ongedaan maken · oefening

Ik heb iets uitgevoerd en nu is mijn werk weg

Iets wat je hebt gecommit is er niet meer. Een opdracht die je half begreep deed iets onverwachts en een stuk echt werk is uit git log verdwenen. Dit is het moment waarop mensen zeggen dat ze een dag werk kwijt zijn.

De commit kan nog beschikbaar zijn, ook al hoort hij niet meer bij je branch. Deze les laat zien hoe je hem zoekt en het werk terughaalt.

Breng eerst de bijgehouden bestanden op orde

Breng de wandelgids in een veilige beginsituatie voordat je het ontbrekende werk terughaalt. Misschien staat er nog een ongewenste bewerking in route.txt en is scratch.tmp nog klaargezet. Mogelijk heb je die twee vergissingen al opgelost.

Deze eerste opdrachten gooien de voorbereide fout in de route weg. Gebruik ze dus alleen voor dit oefenproject. Bekijk in je eigen repository eerst git status en git diff voordat je een bewerking weggooit die je misschien nodig hebt.

git restore --staged . verwijdert eerst de klaargezette wijzigingen onder de huidige map uit de momentopname voor de volgende commit. De punt betekent deze map en alles eronder. Hier begint de terminal in de hoofdmap van het project, dus dat omvat het hele project. Daarna zet git restore route.txt de bijgehouden route terug naar de versie van de nieuwste commit. Geen van beide opdrachten verwijdert scratch.tmp of packing.txt.

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

git status kan scratch.tmp en packing.txt nu als untracked tonen. Die bestanden overlappen niet met het ontbrekende weerbestand en kunnen veilig naast het herstel blijven bestaan. Er hoort geen klaargezette wijziging en geen gewijzigd bijgehouden bestand meer te zijn.

Het ontbrekende werk

De wandelgids had een deel over het weer in de vallei: een paar alinea’s over bewolking die tot de middag blijft hangen en welke voorspelling je kunt vertrouwen. De shellopdracht ls toont de namen in de huidige map. Gebruik die samen met de geschiedenis om zowel de commit als het bestand te zoeken:

git log
ls

Het staat niet in de geschiedenis en weather.md staat niet op schijf. Op een bepaald moment voerde iemand git reset --hard uit. Dat verplaatst de branch terug en herschrijft de werkboom om ermee overeen te komen. De commit hoorde niet meer bij de branch. Op alle gewone manieren van kijken lijkt hij weg.

Git houdt een dagboek bij

Dit is het deel dat bijna niemand te horen krijgt. Git houdt lokale logboeken bij van recente verplaatsingen van verwijzingen. Die heten reflogs. git reflog zonder opties toont de recente posities van HEAD in deze repository.

git reflog

Het nieuwste item staat bovenaan. Van onder naar boven lezen vertelt dus het verhaal van de repository. Heb je de eerdere lessen gevolgd, dan staan je eigen amend-, reset- en revertbewerkingen boven de oudere, voorbereide vermeldingen. Dat is nuttig bewijs, geen rommel: de reflog legt vast wat er werkelijk in deze lokale repository gebeurde.

Zoek de vermelding commit: Write up the weather section. De voorbereide regel reset: moving to HEAD~1 direct erboven markeert het moment waarop Git die commit achterliet. Er kan een nieuwere reset staan uit de eerdere les over privécommits. Daarom herken je het gezochte werk aan het bericht over het weer, niet alleen aan het woord reset.

Elke regel begint met een korte identificatiecode en heeft ook een naam in de vorm HEAD@{n}: “waar HEAD n verplaatsingen geleden stond”. Het getal hangt af van wat je in deze werkruimte hebt gedaan. Beide namen op de weervermelding duiden die commit aan.

In deze voorbereide repository bestaat de commit nog, ook al wijst geen branch ernaar. De reflog geeft je een identificatiecode waarmee je hem kunt bereiken.

Haal het terug

Je wilt het werk van die commit in je huidige branch. git cherry-pick neemt een commit uit de repository en past hem toe op de plek waar je nu bent:

git cherry-pick 3e78e25
git log
ls

Die identificatiecode staat op de regel commit: Write up the weather section. Ze is hier voor iedereen gelijk, omdat elke cursist met dezelfde voorbereide repository begint. In je eigen projecten is ze telkens anders. Leer haar daarom uit je eigen git reflog af te lezen in plaats van haar te onthouden.

git log toont het weerdeel nu weer in de geschiedenis. weather.md staat op schijf, met de alinea’s intact. Het was er al die tijd al.

Wat dit vernietigt en wat niet

git reflog leest alleen. Het verandert helemaal niets en je kunt het zo vaak uitvoeren als je wilt. Als je schrikt, voer dit dan eerst uit.

git cherry-pick maakt een commit op je huidige branch zonder de commits te herschrijven die al in de bereikbare geschiedenis staan. Ook de broncommit blijft onaangeraakt.

Twee grenzen zijn van belang. De reflog is lokaal: hij beschrijft jouw repository, niet die van iemand anders. Een nieuwe clone heeft een eigen reflog. Vermeldingen kunnen verlopen en bij het opschonen van de repository kunnen commits verdwijnen die niet langer worden bewaard. Instellingen en opschoning bepalen hoelang herstel mogelijk blijft. Onderzoek het dus snel, in plaats van te rekenen op een gegarandeerd aantal weken. Ook kan deze methode geen bewerkingen herstellen die Git nooit heeft vastgelegd.

De nuttige gewoonte is eerst kijken, voordat je weer iets verandert. Een ontbrekende vermelding in git log is een reden om git reflog te bekijken, de gewenste commit te vinden en hem terug te halen zolang hij nog beschikbaar is.

Je reset een branch en raakt een commit kwijt. Daarna voer je git reflog zonder opties uit. Waar kijk je naar?

Dat was het hoofdstuk. Zes vragen, zes antwoorden en één onderliggend idee: Git voegt veel vaker toe dan het verwijdert. Wat vernietigd lijkt, heeft meestal alleen geen verwijzing meer.