Wij kunnen een toepassing compromitteren door problematische code te samenvoegen, of het nu door onbedoeld onvoltooid werk integreren in de hoofdtak of door een kritieke bug over het hoofd te zien die de geautomatiseerde tests passeerde.
In dit artikel zal ik je begeleiden door het proces van het veilig ongedaan maken van een samenvoeging met git revert
, zodat de commitgeschiedenis intact blijft en de integriteit van het project bewaard blijft.
Hoe git revert
Werkt
Wij kunnen git revert
zien als Git’s versie van een ongedaan maken commando. Echter, het git revert
commando verwijdert geen commits of springt naar een vorige staat van de tak. In plaats daarvan creëert het een nieuwe commit die de wijzigingen van een specifieke commit ongedaan maakt.
De syntaxis om een commit met hash <commit_hash>
ongedaan te maken is:
git revert <commit_hash>
We kunnen de commits samen met hun hash-identificatoren lijsten met behulp van het git log
commando. De uitvoer van git log
vermeldt de commits van meest recent naar oudste commit, zoals bijvoorbeeld:
Bijvoorbeeld, om de commit die de aftrekfunctie implementeert ongedaan te maken, zouden we het volgende commando gebruiken:
git revert 7ba24a3e62d4d37182428ccfaa070baa222b1151
Met git revert
kunnen we de wijzigingen van een specifieke commit ongedaan maken zonder de commitgeschiedenis te beïnvloeden.
Merk op dat git revert
geen magische handeling is en afhankelijk van de commitgeschiedenis kan het resulteren in een conflict dat handmatig opgelost moet worden.
Voordelen van git revert
ten opzichte van handmatige wijzigingen
Waarom is git revert
nuttig als we mogelijk een conflict handmatig moeten oplossen? Zou het niet eenvoudiger zijn om gewoon handmatig de wijzigingen ongedaan te maken? Laten we de voordelen bekijken:
- Bewaart geschiedenis:
git revert
maakt een nieuwe commit die de wijzigingen van een specifieke commit ongedaan maakt, terwijl de gehele commitgeschiedenis bewaard blijft. Dit helpt bij het handhaven van een transparente geschiedenis van wijzigingen en teruggangen. - Atomaire teruggang: Het zorgt ervoor dat de teruggangen atomaire en consistent zijn. Wanneer we handmatig wijzigingen verwijderen en committen, bestaat er een risico op menselijke fouten.
- Conflictbewustzijn: Het zorgt ervoor dat we worden gewaarschuwd door conflicten als er integraties of wijzigingen zijn die afhankelijk zijn van de oorspronkelijke commit. Dit lijkt misschien ongemakkelijk, maar het beschermt tegen onbedoelde neveneffecten.
- Metadata: De nieuwe commit die door git revert wordt gemaakt, bevat metadata en een commitbericht dat contextueel beschrijft wat is teruggedraaid, wat helpt bij het begrijpen ervan in de toekomst. Zonder
git revert
zou deze context mogelijk verloren gaan.
Terugdraaien van een Samenvoeging in Verschillende Scenario’s
In dit gedeelte leren we hoe we een samenvoeging ongedaan kunnen maken. Voor het voorbeeld veronderstellen we dat we een tak genaamd feature
samenvoegen naar de main
tak door het uitvoeren van de opdracht vanuit de main
tak:
git merge feature
Wat we hier leren, kan worden toegepast op elke twee takken door de namen dienovereenkomstig te vervangen.
Het terugdraaien van een samenvoeging die geen geassocieerde commit heeft
De git merge
opdracht creëert niet altijd een nieuwe commit. Een commit wordt alleen aangemaakt als de main
tak afwijkt van de feature
tak. Omdat git revert
een commit nodig heeft om te werken, kunnen we het in dit geval niet gebruiken.
De main
en feature
takken wijken af wanneer er nieuwe commits worden aangemaakt op main
die geen voorouders zijn van de feature
tak. Met andere woorden, er zijn nieuwe commits aangemaakt op main
na het aanmaken van feature
.
Als de takken niet zijn afgeweken, zal Git de opdracht git merge feature
uitvoeren op de main
tak, en zal Git fast-forward gebruiken om te samenvoegen. Dit betekent dat het de HEAD
van de main
tak verplaatst naar de HEAD
van de feature
tak.
We kunnen zien dat dit gebeurd is door te kijken naar het resultaat van git merge
:
Om zo’n samenvoeging ongedaan te maken, hoeven we alleen de HEAD
van de main
tak terug te verplaatsen naar waar deze was. Hiervoor:
- Identificeer de vorige
HEAD
met behulp vangit reflog
- Herstel de
HEAD
naar de vorige door gebruik te maken vangit reset --hard <previous_head>
, waarbij<previous_head>
wordt vervangen door de vorigeHEAD
.
Het resultaat van git reflog
zal er ongeveer zo uit zien:
We kunnen de vorige HEAD
identificeren door te kijken naar de regel die zegt “checkout: moving from feature to main” (het schrijft feature
en main
omdat dat de namen van onze takken zijn).
In dit geval is de vorige head fe59838
. Om de HEAD
van de hoofdbranch terug te zetten naar deze en de samenvoeging ongedaan te maken, gebruiken we het commando:
git reset --hard fe59838
Het ongedaan maken van een samenvoeging die een geassocieerde commit heeft
Als de main
-tak en de feature
-tak zijn afgegaan, dan wordt bij het samenvoegen van twee takken een nieuwe commit aangemaakt, die een samenvoegingscommit wordt genoemd.
De samenvoegingscommit past de wijzigingen van één tak toe op een andere. In dit geval worden de wijzigingen in feature
toegepast op de main
-tak.
Om de wijzigingen op de main
-tak ongedaan te maken, gebruiken we git revert
op de samenvoegingscommit. Dit zal een nieuwe commit aanmaken die de wijzigingen ongedaan maakt die met de samenvoeging zijn toegevoegd aan de main
-tak, waardoor de staat van de hoofdbranch effectief wordt hersteld naar wat het was voordat de samenvoeging plaatsvond.
Eerst moeten we het hash van de merge commit identificeren. We kunnen dit doen met de git log
opdracht:
Because the merge commit has two parents, the syntax of git revert
is slightly different. We need to use the -m 1
option to specify that we want to revert the changes relative to the main
branch:
git revert -m 1 b8dab2c8611e324ed0d273133987415350e6d10d
Conflict Resolution When Reverting a Commit
Soms kunnen er conflicten optreden bij het terugdraaien van een commit, vooral als de commit die wordt teruggedraaid in botsing komt met latere wijzigingen in de codebase. In dat geval:
- Git zal de revert pauzeren: We moeten handmatig de conflicten oplossen. Git zal de conflicterende bestanden markeren en ingrijpen vereisen.
- Los de conflicten op: We openen elk conflicterend bestand, lossen de door Git gemarkeerde conflicten op, en slaan de wijzigingen op.
- Voeg de opgeloste bestanden toe aan de index:
git add <file-path>
- Ga door met de revert:
git revert --continue
Conclusie
Het gebruik van git revert
om merge commits ongedaan te maken, zorgt ervoor dat elke wijziging en correctie gedocumenteerd blijft binnen de commit geschiedenis.
Daarnaast begrijpen we beter welke scenario’s geschikt zijn om git reset
versus git revert
toe te passen, wat ons helpt om betere beslissingen te nemen, vooral bij samenwerkingswerkflows of alleen lokale wijzigingen.
Je kunt meer lezen over dit onderwerp in het gedeelte Veelgestelde Vragen hieronder. Als je meer wilt leren over Git, raad ik deze bronnen aan: