Commits en wijzigingen ongedaan maken
In deze sectie bespreken we de beschikbare Git-strategieën en -opdrachten om 'ongedaan te maken'. Allereerst moet worden opgemerkt dat Git geen traditioneel systeem voor het 'ongedaan maken' heeft zoals dat in een tekstverwerkingsprogramma wordt aangetroffen. Het is verstandig om Git-operaties niet toe te wijzen aan een traditioneel mentaal model voor 'ongedaan maken'. Daarnaast heeft Git een eigen naamgeving voor werkzaamheden voor 'ongedaan maken', die je het beste kunt gebruiken in een discussie. Deze naamgeving omvat termen als resetten, terugzetten, uitchecken, opschonen en meer.
Een leuke metafoor is om Git te zien als een hulpmiddel voor tijdlijnbeheer. Commits zijn momentopnamen van een tijdstip of aandachtspunt op de tijdlijn van de geschiedenis van een project. Bovendien kunnen meerdere tijdlijnen worden beheerd door het gebruik van branches. Bij het 'ongedaan maken' in Git ga je meestal terug in de tijd, of naar een andere tijdlijn waar geen fouten zijn gemaakt.
Deze tutorial verschaft alle vaardigheden die nodig zijn om met eerdere revisies van een softwareproject te werken. Eerst laat deze zien hoe je oude commits kunt verkennen, en dan verklaart deze het verschil tussen het terugdraaien van openbare commits in de projectgeschiedenis en het opnieuw instellen van niet-gepubliceerde wijzigingen op je lokale computer.
Terugvinden wat verloren is gegaan: oude commits bekijken
Het hele idee achter elk versiebeheersysteem is om 'veilige' kopieën van een project op te slaan, zodat je je nooit zorgen hoeft te maken dat je codebasis onherstelbaar wordt doorbroken. Als je eenmaal een projectgeschiedenis van commits hebt opgebouwd, kun je elke commit in de geschiedenis controleren en opnieuw bekijken. Een van de beste hulpprogramma's om de geschiedenis van een Git-repository te controleren, is de opdracht git log
. In het onderstaande voorbeeld gebruiken we git log om een lijst te krijgen van de meest recente commits voor een populaire opensource-afbeeldingenbibliotheek.
git log --oneline
e2f9a78fe Replaced FlyControls with OrbitControls
d35ce0178 Editor: Shortcuts panel Safari support.
9dbe8d0cf Editor: Sidebar.Controls to Sidebar.Settings.Shortcuts. Clean up.
05c5288fc Merge pull request #12612 from TyLindberg/editor-controls-panel
0d8b6e74b Merge pull request #12805 from harto/patch-1
23b20c22e Merge pull request #12801 from gam0022/improve-raymarching-example-v2
fe78029f1 Fix typo in documentation
7ce43c448 Merge pull request #12794 from WestLangley/dev-x
17452bb93 Merge pull request #12778 from OndrejSpanel/unitTestFixes
b5c1b5c70 Merge pull request #12799 from dhritzkiv/patch-21
1b48ff4d2 Updated builds.
88adbcdf6 WebVRManager: Clean up.
2720fbb08 Merge pull request #12803 from dmarcos/parentPoseObject
9ed629301 Check parent of poseObject instead of camera
219f3eb13 Update GLTFLoader.js
15f13bb3c Update GLTFLoader.js
6d9c22a3b Update uniforms only when onWindowResize
881b25b58 Update ProjectionMatrix on change aspect
gerelateerd materiaal
Git cheat sheet
Oplossing bekijken
Git leren met Bitbucket Cloud
Elke commit heeft een unieke SHA-1-identificerende hash. Deze ID's worden gebruikt om de vastgelegde tijdlijn te doorlopen en commits opnieuw te bekijken. git log
toont standaard alleen commits voor de momenteel geselecteerde branch. Het is heel goed mogelijk dat de commit die je zoekt zich in een andere branch bevindt. Je kunt alle commits in alle branches bekijken door git log --branches=*
uit te voeren. De opdracht git branch wordt gebruikt om andere branches te bekijken en te bezoeken. Door de opdracht te activeren, retourneert git branch -a
een lijst met alle bekende branchnamen. Een van deze branchnamen kan dan worden geregistreerd met git log
.
Als je een doorverwijzing hebt gevonden naar het punt in de geschiedenis dat je wilt bezoeken, kun je de opdracht git checkout
gebruiken om naar die commit te gaan. Git checkout
is een eenvoudige manier om al deze opgeslagen momentopnamen naar je ontwikkelmachine te 'laden'. Tijdens de normale ontwikkelingsfase verwijst HEAD
meestal naar de main
of een andere lokale branch, maar als je een vorige commit uitcheckt, wijst HEAD
niet langer naar een branch, maar rechtstreeks naar een commit. Dit wordt een 'detached HEAD
'-status genoemd en kan als volgt worden gevisualiseerd:
Bij het uitchecken van een oud bestand wordt de HEAD
-pointer niet verplaatst. Deze blijft op dezelfde branch en op dezelfde commit staan, waarbij een toestand van 'detached head' wordt vermeden. Je kunt dan de oude versie van het bestand committen in een nieuwe momentopname, net als elke andere wijziging. In feite dient dit gebruik van git checkout
in een bestand dus als een manier om terug te keren naar een oude versie van een individueel bestand. Ga voor meer informatie over deze twee modi naar de pagina git checkout
Een oude herziening bekijken
In dit voorbeeld wordt ervan uitgegaan dat je bent begonnen met het ontwikkelen van een gek experiment, maar je weet niet zeker of je het wilt houden of niet. Om je te helpen een beslissing te nemen, wil je eerst naar de staat van het project kijken voordat je aan je experiment begint. Eerst moet je de ID vinden van de herziening die je wilt bekijken.
git log --oneline
Stel dat de geschiedenis van je project er ongeveer als volgt uitziet:
b7119f2 Continue doing crazy things
872fa7e Try something crazy
a1e8fb5 Make some important changes to hello.txt
435b61d Create hello.txt
9773e52 Initial import
Je kunt git checkout
gebruiken door de commit 'Make some import changes to hello.txt' te bekijken:
git checkout a1e8fb5
Dit zorgt ervoor dat je werkmap exact overeenkomt met de status van de commit a1e8fb5
. Je kunt bestanden bekijken, het project samenstellen, testen uitvoeren en zelfs bestanden bewerken zonder je zorgen te hoeven maken dat de huidige status van het project verloren gaat. Niets wat je hier doet, wordt opgeslagen in je repository. Om je verder te ontwikkelen, moet je teruggaan naar de 'huidige' status van je project:
git checkout main
Hierbij wordt ervan uitgegaan dat je je ontwikkelt in de standaard main
-branch. Als je eenmaal terug bent in de main
-branch, kun je git revert of git reset gebruiken om ongewenste wijzigingen ongedaan te maken.
Een gecommitte momentopname ongedaan maken
Technisch gezien zijn er verschillende strategieën om een commit 'ongedaan te maken'. In de volgende voorbeelden wordt ervan uitgegaan dat we een commit-geschiedenis hebben die er als volgt uitziet:
git log --oneline
872fa7e Try something crazy
a1e8fb5 Make some important changes to hello.txt
435b61d Create hello.txt
9773e52 Initial import
We zullen ons concentreren op het ongedaan maken van de commit 872fa7e Try something crazy
. Misschien werd het een beetje te gek.
Hoe maak je een commit ongedaan met git checkout
Met de opdracht git checkout
kunnen we de vorige commit a1e8fb5
uitchecken, waardoor de repository in een toestand wordt teruggezet voordat de gekke commit plaatsvond. Als je een specifieke commit bekijkt, wordt de repo in een aparte 'detached HEAD'-status geplaatst. Dit betekent dat je in geen enkele branch meer werkt. In een vrijstaande staat worden alle nieuwe commits die je doet verweesd als je terugkeert naar een gevestigde branch. Verweesde commits worden verwijderd door de vuilnisophaler van Git. De vuilnisophaler wordt op schema uitgevoerd en vernietigt verweesde commits permanent. Om te voorkomen dat verweesde commits worden opgehaald als afval, moeten we ervoor zorgen dat we ons in een branch bevinden.
Vanuit de 'detached HEAD'-status kunnen we git checkout -b new_branch_without_crazy_commit
uitvoeren. Hierdoor wordt een nieuwe branch aangemaakt, genaamd new_branch_without_crazy_commit
, en wordt er naar die status overgeschakeld. De repo bevindt zich nu op een nieuwe historische tijdlijn waarin de commit 872fa7e
niet langer bestaat. Op dit moment kunnen we blijven werken aan deze nieuwe branch waarin de commit 872fa7e
niet langer bestaat en deze als 'ongedaan gemaakt' beschouwen. Als je echter de vorige branch nodig hebt, misschien je main
-branch, is deze strategie om ongedaan te maken niet geschikt. Laten we eens kijken naar enkele andere strategieën om dingen 'ongedaan te maken'. Bekijk onze uitgebreide discussie over git checkout voor meer informatie en voorbeelden.
Hoe maak je een publieke commit ongedaan met git revert
Laten we aannemen dat we terug zijn bij ons oorspronkelijke voorbeeld van de commit-geschiedenis. De geschiedenis die de commit 872fa7e
bevat. Laten we deze keer proberen om het 'ongedaan maken' terug te draaien. Als we git revert HEAD
uitvoeren, zal Git een nieuwe commit aanmaken met het omgekeerde van de laatste commit. Dit voegt een nieuwe commit toe aan de huidige geschiedenis van de branch en het ziet er nu als volgt uit:
git log --oneline
e2f9a78 Revert "Try something crazy"
872fa7e Try something crazy
a1e8fb5 Make some important changes to hello.txt
435b61d Create hello.txt
9773e52 Initial import
Op dit moment hebben we technisch gezien de commit 872fa7e
opnieuw 'ongedaan gemaakt'. Hoewel 872fa7e
nog steeds bestaat in de geschiedenis, is de nieuwe commit e2f9a78
een omgekeerde van de veranderingen in 872fa7e
. In tegenstelling tot onze vorige uitcheckstrategie kunnen we dezelfde branch blijven gebruiken. Deze oplossing is voldoende. Dit is de ideale methode om 'ongedaan te maken' om te werken met openbare gedeelde repository's. Als je een gecureerde en minimale Git-geschiedenis wilt bijhouden, is deze strategie misschien niet voldoende.
Hoe maak je een commit ongedaan met git reset
Voor deze strategie om ongedaan te maken, gaan we door met ons werkende voorbeeld. git reset is een uitgebreide opdracht met meerdere toepassingen en functies. Als we git reset --hard a1e8fb5
activeren, wordt de commit-geschiedenis teruggezet naar de gespecificeerde commit. De commit-geschiedenis bekijken met git log
zal er nu als volgt uitzien:
git log --oneline
a1e8fb5 Make some important changes to hello.txt
435b61d Create hello.txt
9773e52 Initial import
De output van de log toont aan dat de commits e2f9a78
en 872fa7e
niet meer voorkomen in de commit-geschiedenis. Op dit moment kunnen we doorgaan met werken en nieuwe commits creëren alsof de 'gekke' commits nooit zijn voorgekomen. Deze methode om wijzigingen ongedaan te maken heeft het meest zuivere effect op de geschiedenis. Een reset uitvoeren is geweldig voor lokale wijzigingen, maar het brengt complicaties met zich mee als je met een gedeelde externe repository werkt. Als we een gedeelde externe repository hebben waar de commit 872fa7e
naartoe is gepusht, en we proberen git push
voor een branch waar we de geschiedenis opnieuw hebben ingesteld, dan vangt Git dit op en genereert een foutmelding. Git gaat ervan uit dat de branch die wordt gepusht niet up-to-date is omdat er commits ontbreken. In deze scenario's zou git revert
de voorkeursmethode voor ongedaan maken moeten zijn.
De laatste commit ongedaan maken
In het vorige gedeelte hebben we verschillende strategieën besproken om commits ongedaan te maken. Deze strategieën zijn ook allemaal van toepassing op de meest recente commit. In sommige gevallen is het echter mogelijk dat je de laatste commit niet hoeft te verwijderen of resetten. Misschien is deze gewoon te vroeg gemaakt. In dat geval kun je de meest recente commit aanpassen. Als je eenmaal meer wijzigingen hebt aangebracht in de werkmap en ze hebt gestaged voor commit met git add
, kun je git commit --amend uitvoeren. Hiermee opent Git de geconfigureerde systeemeditor en kun je het laatste commit-bericht wijzigen. De nieuwe wijzigingen worden toegevoegd aan de gewijzigde commit.
Niet gecommitte wijzigingen ongedaan maken
Voordat wijzigingen worden doorgevoerd in de geschiedenis van de repository, bevinden ze zich in de staging-index en in de werkmap. Het kan nodig zijn om wijzigingen binnen deze twee gebieden ongedaan te maken. De staging-index en de werkmap zijn interne mechanismen voor het beheer van de Git-status. Ga voor meer gedetailleerde informatie over hoe deze twee mechanismen werken naar de pagina git reset, waar ze uitgebreid worden verkend.
De werkmap
De werkmap is over het algemeen gesynchroniseerd met het lokale bestandssysteem. Om wijzigingen in de werkmap ongedaan te maken, kun je bestanden bewerken zoals je dat normaal zou doen met je favoriete editor. Git heeft een aantal hulpprogramma's die helpen bij het beheren van de werkmap. Er is de opdracht git clean, een handig hulpmiddel om wijzigingen in de werkmap ongedaan te maken. Daarnaast kan git reset
worden aangeroepen met de opties --mixed
of --hard
, waardoor een reset wordt toegepast op de werkmap.
De staging-index
De opdracht git add wordt gebruikt om wijzigingen toe te voegen aan de staging-index. Git reset
wordt voornamelijk gebruikt om wijzigingen in de staging-index ongedaan te maken. Een --mixed
reset verplaatst alle openstaande wijzigingen van de testindex terug naar de werkmap.
Openbare wijzigingen ongedaan maken
Als je in een team met externe repository's werkt, moet er extra aandacht worden besteed aan het ongedaan maken van wijzigingen. Git reset
moet over het algemeen worden beschouwd als een 'lokale' methode voor ongedaan maken. Een reset moet worden gebruikt om wijzigingen in een privébranch ongedaan te maken. Dit isoleert op een veilige manier het verwijderen van commits uit andere branches die mogelijk door andere ontwikkelaars worden gebruikt. Er doen zich problemen voor wanneer een reset wordt uitgevoerd op een gedeelde branch en die branch vervolgens op afstand wordt gepusht met git push
. Git blokkeert de push in dit scenario door te melden dat de branch die wordt gepusht verouderd is en afkomstig is van de externe branch omdat er commits ontbreken.
De voorkeursmethode om gedeelde geschiedenis ongedaan te maken is git revert
. Terugzetten is veiliger dan opnieuw instellen, omdat hiermee geen commits uit een gedeelde geschiedenis worden verwijderd. Bij terugzetten worden de commits bewaard die je ongedaan wilt maken en wordt een nieuwe commit aangemaakt die de ongewenste commit omkeert. Deze methode is veiliger voor gedeelde samenwerking op afstand, omdat een externe ontwikkelaar dan de branch kan pullen en de nieuwe revert-commit kan ontvangen, waardoor de ongewenste commit ongedaan wordt gemaakt.
Samenvatting
We hebben veel strategieën op hoog niveau besproken om dingen ongedaan te maken in Git. Het is belangrijk om te onthouden dat er in een Git-project meer dan één manier is om 'ongedaan te maken'. Wat op deze pagina het meest besproken is, waren diepergaande onderwerpen die grondiger worden uitgelegd op pagina's die specifiek zijn voor de relevante Git-opdrachten. De meest gebruikte tools voor 'ongedaan maken' zijn git checkout, git revert en git reset. Enkele belangrijke punten om te onthouden zijn:
- Zodra wijzigingen zijn doorgevoerd, zijn ze over het algemeen permanent
- Gebruik
git checkout
om te navigeren en de commit-geschiedenis te bekijken git revert
is de beste tool om gedeelde openbare wijzigingen ongedaan te makengit reset
is geschikt om lokale privéwijzigingen ongedaan te maken
Naast de primaire opdrachten voor 'ongedaan maken' hebben we ook andere Git-hulpprogramma's bekeken: git log voor het vinden van verloren commits; git clean voor het ongedaan maken van niet-gecommitte wijzigingen; git add voor het wijzigen van de staging-index.
Elk van deze opdrachten heeft zijn eigen uitgebreide documentatie. Bezoek de bijbehorende links voor meer informatie over een specifieke opdracht die hier wordt genoemd.
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.