Close

Resetting, checking out & reverting


The git reset, git checkout, and git revert commands are some of the most useful tools in your Git toolbox. They all let you undo some kind of change in your repository, and the first two commands can be used to manipulate either commits or individual files.

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.

De drie bomen van Git

It helps to think about each command in terms of their effect on the three state management mechanisms of a Git repository: the working directory, the staged snapshot, and the commit history. These components are sometimes known as "The three trees" of Git. We explore the three trees in depth on the git reset page. Keep these mechanisms in mind as you read through this article.

Een checkout is een bewerking waarbij de ref-pointer HEAD naar een gespecificeerde commit wordt verplaatst. Bekijk het volgende voorbeeld waarin we dit aantonen.

Verplaats de HEAD-ref-pointer naar een gespecificeerde commit
Databases
gerelateerd materiaal

Een volledige Git-repository verplaatsen

Logo Bitbucket
Oplossing bekijken

Git leren met Bitbucket Cloud

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

Sequence of commits on the main branch

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.

Git reset vs revert vs checkout reference


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

Scope

Commit-niveau

Veelgebruikte usecases

Discard commits in a private branch or throw away uncommitted changes

git reset

Scope

Bestandsniveau

Veelgebruikte usecases

Een bestand ontstagen

Git Checkout

Scope

Commit-niveau

Veelgebruikte usecases

Tussen branches schakelen of oude momentopnamen bekijken

Git Checkout

Scope

Bestandsniveau

Veelgebruikte usecases

Wijzigingen in de werkmap negeren

git revert

Scope

Commit-niveau

Veelgebruikte usecases

Commits in een openbare branch ongedaan maken

git revert

Scope

Bestandsniveau

Veelgebruikte usecases

(n.v.t.)

Commit level operations


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.

Reset a specific commit

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:

De hotfix-branch opnieuw instellen als HEAD-2

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.

It’s easier to think of these modes as defining the scope of a git reset operation. For further detailed information visit the git reset page.

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.

Moving HEAD from main to hotfix

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
'HEAD' verplaatsen naar een willekeurige commit

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.

Undo public commits with 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:

De voorlaatste commit terugzetten

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.

File-level operations


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 a specific file

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.

Een bestand verplaatsen van de commit-geschiedenis naar de gestagede momentopname

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 file

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.

Een bestand verplaatsen van de commit-geschiedenis naar de werkmap

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


You should now have all the tools you could ever need to undo changes in a Git repository. The git reset, git checkout, and git revert commands can be confusing, but when you think about their effects on the working directory, staged snapshot, and commit history, it should be easier to discern which command fits the development task at hand.


Deel dit artikel
Volgend onderwerp

Aanbevolen artikelen

Bookmark deze resources voor meer informatie over soorten DevOps-teams of voor voortdurende updates over DevOps bij Atlassian.

Mensen die samenwerken met een muur vol tools

Bitbucket-blog

Toelichting DevOps

DevOps-leertraject

Demo Den Feature-demo's met Atlassian-experts

Hoe Bitbucket Cloud werkt met Atlassian Open DevOps

Meld je aan voor onze DevOps-nieuwsbrief

Thank you for signing up