Resetten, uitchecken en terugzetten
De opdrachten git reset
, git checkout
en git revert
zijn een paar van de handigste tools in je Git-toolbox. Ze laten je allemaal een wijziging in je repository ongedaan maken, en de eerste twee opdrachten kunnen gebruikt worden om commits of afzonderlijke bestanden te manipuleren.
Omdat ze zo op elkaar lijken, is het heel eenvoudig door elkaar te halen welke opdracht in een bepaald ontwikkelingsscenario gebruikt moet worden. In dit artikel vergelijken we de meest voorkomende configuraties van git reset
, git checkout
en git revert
. Hopelijk kun je hierna vol vertrouwen met een van deze opdrachten door je repository navigeren.
Het helpt om over elke opdracht na te denken in termen van hun effect op de drie mechanismen voor statusbeheer van een Git-repository: de werkmap, de gestagede momentopname en de commit-geschiedenis. Deze componenten worden ook wel "de drie bomen" van Git genoemd. We gaan wat dieper in op de drie bomen op de pagina git reset
. Houd deze mechanismen in gedachten terwijl je dit artikel leest.
Een checkout is een bewerking waarbij de ref-pointer HEAD
naar een gespecificeerde commit wordt verplaatst. Bekijk het volgende voorbeeld waarin we dit aantonen.

Dit voorbeeld toont een reeks commits op de branch main
. De referentie HEAD
en de branch main
verwijzen momenteel naar commit d. Laten we nu git checkout b
uitvoeren

Dit is een update van de boom 'commitgeschiedenis'. De opdracht git checkout
kan worden gebruikt in een commit of op bestandsniveau. Bij uitchecken op bestandsniveau wordt de inhoud van het bestand gewijzigd in de inhoud van de specifieke commit.
Een terugdraaiing is een handeling waarbij een specifieke commit gebruikt wordt en een nieuwe commit gemaakt wordt die de gespecificeerde commit omkeert. git revert
kan alleen worden uitgevoerd op commit-niveau en heeft geen functionaliteit op bestandsniveau.
Een reset is een handeling waarbij een specifieke commit nodig is en de 'drie bomen' opnieuw worden ingesteld zodat ze overeenkomen met de status van de repository in die specifieke commit. Een reset kan aangeroepen worden in drie verschillende modi die overeenkomen met de drie bomen.
Uitchecken en resetten worden over het algemeen gebruikt om lokaal of privé 'ongedaan te maken'. Ze wijzigen de geschiedenis van een repository, wat tot conflicten kan leiden bij het pushen naar externe gedeelde repository's. Terugdraaien wordt beschouwd als een veilige handeling voor 'openbaar ongedaan maken' omdat er een nieuwe geschiedenis wordt gecreëerd die op afstand kan worden gedeeld en de geschiedenis waar teamleden op afstand afhankelijk van kunnen zijn, niet overschrijft.
Referentie van git reset vs. revert vs. checkout
De tabel hieronder geeft een overzicht van de meest voorkomende toepassingen van al deze opdrachten. Zorg ervoor dat je deze referentie bij de hand houdt, want je zult er ongetwijfeld minstens een paar moeten gebruiken tijdens je Git-carrière.
Opdracht | Scope | Veelgebruikte usecases |
---|---|---|
git reset | Commit-niveau | Verwerp commits in een privébranch of gooi niet-gecommitte wijzigingen weg |
git reset | Bestandsniveau | Een bestand ontstagen |
Git Checkout | Commit-niveau | Tussen branches schakelen of oude momentopnamen bekijken |
Git Checkout | Bestandsniveau | Wijzigingen in de werkmap negeren |
git revert | Commit-niveau | Commits in een openbare branch ongedaan maken |
git revert | Bestandsniveau | (n.v.t.) |
Handelingen op commit-niveau
De parameters die je doorgeeft aan git reset
en git checkout
bepalen de scope ervan. Als je geen bestandspad als parameter opgeeft, werken ze op basis van volledige commits. Dat bekijken we in dit gedeelte. Let op, git revert
heeft geen tegenhanger op bestandsniveau.
Een specifieke commit resetten
Op commit-niveau is resetten een manier om het uiterste van een branch naar een andere commit te verplaatsen. Dit kan worden gebruikt om commits uit de huidige branch te verwijderen. Met de volgende opdracht wordt de branch hotfix
bijvoorbeeld twee commits terug geplaatst.
git checkout hotfix git reset HEAD~2
De twee commits die aan het einde van de hotfix
stonden, zijn nu losstaande, oftewel verweesde commits. Dit betekent dat ze worden verwijderd de volgende keer dat Git een verwijdering uitvoert. Met andere woorden: je zegt dat je deze commits wilt weggooien. Dit kan als volgt worden gevisualiseerd:

Dit gebruik van git reset
is een eenvoudige manier om wijzigingen ongedaan te maken die nog nooit met iemand anders zijn gedeeld. Dat is je voorkeursopdracht als je aan een functie begint te werken en merkt dat je denkt: 'Verdorie, waar ben ik mee bezig? Ik eigenlijk maar opnieuw beginnen.'
Naast het verplaatsen van de huidige branch, kun je met git reset
de gestagede momentopname en/of de werkmap wijzigen door er een van de volgende vlaggen aan toe te voegen:
--soft
: de gestagede momentopname en werkmap worden op geen enkele manier gewijzigd.--mixed
: de gestagede momentopname is bijgewerkt zodat deze overeenkomt met de opgegeven commit, maar dit heeft geen invloed op de werkmap. Dit is de standaardoptie.--hard
: de gestagede momentopname en de werkmap zijn beide bijgewerkt zodat ze overeenkomen met de opgegeven commit.
Het is makkelijker om deze modi te beschouwen als definities van de scope van een git reset
-handeling. Ga voor meer gedetailleerde informatie naar de pagina git reset
.
Oude commits uitchecken
De opdracht git checkout
wordt gebruikt om de status van de repository bij te werken naar een specifiek punt in de geschiedenis van het project. Als er een branchnaam wordt doorgegeven, kun je tussen branches schakelen.
git checkout hotfix
Intern verplaatst de bovenstaande opdracht alleen maar HEAD
naar een andere branch en werkt deze de werkmap bij zodat deze overeenkomt. Aangezien dit lokale wijzigingen kan overschrijven, dwingt Git je om alle wijzigingen in de werkmap die verloren gaan tijdens het uitchecken, door te voeren of te stashen. In tegenstelling tot git reset
verplaatst git checkout
geen branches.

Je kunt ook willekeurige commits uitchecken door de commit-referentie door te geven in plaats van een branch. Hierdoor wordt precies hetzelfde gedaan als bij het uitchecken van een branch: het verplaatst de HEAD
-referentie naar de gespecificeerde commit. De volgende opdracht checkt bijvoorbeeld het hoogst gelegen item uit van de huidige commit:
git checkout HEAD~2
Dit is handig om snel een oude versie van je project te inspecteren. Aangezien er echter geen branchverwijzing is naar de huidige HEAD
, zit je in een aparte HEAD
-status. Dit kan gevaarlijk zijn als je nieuwe commits gaat toevoegen, omdat je daar niet meer naar terug kunt als je naar een ander branch overschakelt. Daarom moet je altijd een nieuwe branch aanmaken voordat je commits toevoegt aan een aparte HEAD
.
Openbare commits ongedaan maken met Revert
Terugdraaien maakt een commit ongedaan door een nieuwe commit aan te maken. Dit is een veilige manier om wijzigingen ongedaan te maken, aangezien er geen kans is dat de commit-geschiedenis wordt herschreven. De volgende opdracht berekent bijvoorbeeld de wijzigingen in de voorlaatste commit, maakt een nieuwe commit aan om deze wijzigingen ongedaan te maken, en wijst de nieuwe commit toe aan het bestaande project.
git checkout hotfix git revert HEAD~2
Dit kan als volgt worden gevisualiseerd:
Vergelijk dit met git reset
, wat wel de bestaande commit-geschiedenis verandert. Om deze reden moet git revert
gebruikt worden om wijzigingen ongedaan te maken in een openbare branch, en git reset
moet gereserveerd worden voor het ongedaan maken van wijzigingen in een privébranch.
Je kunt git revert
ook zien als tool om gecommitte wijzigingen ongedaan te maken, terwijl git reset HEAD
bedoeld is om niet-gecommitte wijzigingen ongedaan te maken.
Net als git checkout
kan git revert
bestanden in de werkmap overschrijven. Je zult dus gevraagd worden om te committen of wijzigingen te stashen die verloren zouden gaan tijdens het terugzetten.
Handelingen op bestandsniveau
De opdrachten git reset
en git checkout
accepteren ook een optioneel bestandspad als parameter. Dit verandert het gedrag ervan ingrijpend. In plaats van volledige momentopnamen te maken, worden ze gedwongen de handeling te beperken tot één bestand.
Git reset van een specifiek bestand
Wanneer opgeroepen met een bestandspad, wordt de gestagede momentopname bijgewerkt door git reset
zodat deze overeenkomt met de versie van de gespecificeerde commit. Deze opdracht haalt bijvoorbeeld de versie van foo.py
op in de voorlaatste commit en staget deze voor de volgende commit:
git reset HEAD~2 foo.py
Net als bij de versie op commit-niveau van git reset
, wordt dit vaker gebruikt met HEAD
in plaats van met een willekeurige commit. Het uitvoeren van git reset HEAD foo.py
zorgt dat foo.py
ontstaged wordt. De daarin opgenomen wijzigingen zijn nog steeds aanwezig in de werkmap.
De vlaggen --soft
, --mixed
en --hard
hebben geen enkel effect op de bestandsversie van git reset
, aangezien de gestagede momentopname altijd wordt bijgewerkt en de werkmap nooit wordt bijgewerkt.
git checkout van bestand
Een bestand uitchecken is vergelijkbaar met het gebruik van git reset
met een bestandspad, maar nu wordt de werkmap bijgewerkt in plaats van het staginggebied. In tegenstelling tot de commit-versie van deze opdracht wordt hiermee de HEAD
-referentie niet verplaatst, wat betekent dat je niet van branch wisselt.
De volgende opdracht zorgt er bijvoorbeeld voor dat foo.py
in de werkmap overeenkomt met dat van de voorlaatste commit:
git checkout HEAD~2 foo.py
Net zoals bij het aanroepen van git checkout
op commit-niveau kan dit worden gebruikt om oude versies van een project te inspecteren, maar de scope is beperkt tot het opgegeven bestand.
Als je het uitgecheckte bestand staget en commit, wordt deze 'teruggezet' naar de oude versie van dat bestand. Let op dat hiermee alle daaropvolgende wijzigingen aan het bestand worden verwijderd, terwijl de opdracht git revert
alleen de wijzigingen ongedaan maakt die door de opgegeven commit zijn geïntroduceerd.
Zoals bij git reset
wordt dit vaak gebruikt met HEAD
als commit-referentie. git checkout HEAD foo.py
heeft bijvoorbeeld tot gevolg dat niet-gestagede wijzigingen in foo.py
genegeerd worden. Dit gedrag lijkt op dat bij git reset HEAD --hard
, maar het werkt alleen op het opgegeven bestand.
Samenvatting
Je zou nu over alle tools moeten beschikken die je nodig hebt om wijzigingen ongedaan te maken in een Git-repository. De opdrachten git reset
, git checkout
en git revert
kunnen verwarrend zijn, maar als je nadenkt over de effecten ervan op de werkmap, de gestagede momentopname en de commit-geschiedenis, zou het eenvoudiger moeten zijn om te onderscheiden welke opdracht past bij de ontwikkelingstaak die voor de boeg ligt.