Git Revert Merge Commit: Een Gids Met Voorbeelden

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:

  1. Identificeer de vorige HEAD met behulp van git reflog
  2. Herstel de HEAD naar de vorige door gebruik te maken van git reset --hard <previous_head>, waarbij <previous_head> wordt vervangen door de vorige HEAD.

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:

  1. Git zal de revert pauzeren: We moeten handmatig de conflicten oplossen. Git zal de conflicterende bestanden markeren en ingrijpen vereisen.
  2. Los de conflicten op: We openen elk conflicterend bestand, lossen de door Git gemarkeerde conflicten op, en slaan de wijzigingen op.
  3. Voeg de opgeloste bestanden toe aan de index: git add <file-path>
  4. 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:

Source:
https://www.datacamp.com/tutorial/git-revert-merge