Een doorloop van de tutorial Een commit ongedaan maken: waarom de laatste commit kapot is en hoe git reset --soft je hem laat herstellen zonder werk te verliezen.
Dit scenario begint in een portfolio-project waar de laatste commit subtiel kapot is. Je leest de geschiedenis, maakt die commit ongedaan terwijl je je wijzigingen behoudt, en commit hem opnieuw goed. Hier is wat er in elke stap gebeurt en waarom.
De situatie
Het project heeft twee commits. De meest recente, "Add header section", voegde een navigatie-header toe aan index.html. De bijbehorende CSS voor die header is in style.css geschreven, maar werd nooit gestaged: het staat nog steeds als niet-gecommite wijziging in de werkboom.
De commit is dus onvolledig. De gecommite site bevat header-markup die verwijst naar stijlen die niet zijn opgeslagen. Wie deze commit uitcheckt, ziet een kapotte header.
Start met git log --oneline en git status. Het log toont de commit "Add header section"; status toont style.css als gewijzigd maar niet gestaged. Dat verschil ís het hele probleem.
De oplossing, stap voor stap
Bekijken wat is gecommit
git log bevestigt de laatste commit en git status toont dat style.css nog steeds gewijzigd in de werkboom staat. Nu weet je dat de commit index.html heeft vastgelegd maar niet style.css.
De commit ongedaan maken, wijzigingen behouden
git reset --soft HEAD~1
Dit zet de branchwijzer één commit terug. De index.html-wijziging die in de commit zat keert terug naar de stagingruimte, klaar om opnieuw te worden gecommit. Niets in je bestanden wordt verwijderd.
Deze keer alles stagen
git add index.html style.css
Nu staan de markup en de bijhorende stijlen samen gestaged, zodat de volgende commit volledig wordt.
De volledige wijziging opnieuw committen
git commit -m "Add header section"
De geschiedenis heeft weer één commit "Add header section", maar deze keer inclusief style.css. De site is heel.
Waarom --soft hier de juiste modus is
git reset heeft drie modi, en het verschil zit alleen in waar je wijzigingen belanden:
--soft zet HEAD terug en houdt de wijzigingen gestaged. Hier ideaal omdat je meteen opnieuw wilt committen.
--mixed (de standaard) behoudt de wijzigingen maar niet-gestaged, in de werkboom.
--hard gooit de wijzigingen volledig weg.
git reset --hard HEAD~1 zou hier het header-werk samen met de commit verwijderen. Reserveer --hard voor wanneer je de wijzigingen echt kwijt wilt.
Als je per ongeluk --hard uitvoert, is de commit meestal nog te redden met git reflog, dat elke positie van HEAD opsomt. De tutorial "Recover Lost Commits" behandelt die flow.
Eén kanttekening: gedeelde commits
Al het bovenstaande herschrijft geschiedenis, wat volkomen veilig is voor een commit die alleen op je eigen machine bestaat. Zodra een commit is gepusht en door anderen is gepulld, dwingt herschrijven iedereen tot een afwijkende branch. Op een gedeelde branch draai je de wijziging terug met een nieuwe commit:
git revert HEAD