Een Gids voor Git Interactive Rebase, met Praktische Voorbeelden

Versiebeheer met Git is uitgegroeid tot een standaard in het gereedschapsset van elke moderne ontwikkelaar. Opdrachten zoals commit, push en pull zijn in ons vingermuscle-geheugen terechtgekomen. Maar relatief weinig ontwikkelaars kennen de “geavanceerdere” functies van Git – en hoe ongelooflijk waardevol ze kunnen zijn! In dit artikel gaan we “interactieve rebase” onder de loep nemen, een van de krachtigste tools in Git.

Waarom Interactieve Rebase deel uitmaken van iedere ontwikkelaarstools

Kort gezegd, en zonder overdrijving, kan interactieve rebase je helpen een betere ontwikkelaar te worden door het creëren van een nette en goed gestructureerde commithistorie in je projecten.

Waarom is een goed gestructureerde commithistorie belangrijk? Stel je de tegenovergestelde situatie voor: een moeilijk te lezen commithistorie, waar je geen idee hebt wat je collega’s eigenlijk hebben gedaan met hun recente wijzigingen. Steeds meer “donkere hoeken” beginnen zich te openbaren in zo’n project, en je begrijpt alleen de kleine delen waar je zelf aan gewerkt hebt.

Vergelijk dit met een nette en goed gestructureerde commithistorie: het helpt een projectcodebase leesbaarder en makkelijker te begrijpen. Dit is een essentieel ingrediënt voor een gezond, langdurig project!

Wat Interactieve Rebase voor je kan doen

Interactieve Rebase helpt je je commithistorie te optimaliseren en op te poetsen. Het omvat veel verschillende gebruiksvoorbeelden, waarvan sommige je de volgende mogelijkheden bieden:

  • een oude committeraad te bewerken
  • een commit te verwijderen
  • meerdere commits samen te voegen/samen te voegen
  • commits te herordenen
  • repareren oude commits
  • splitsen/reopenen oude commits voor bewerking

Wanneer te gebruiken Interactive Rebase (en wanneer niet!)

Net als een paar andere Git-gereedschappen, “herschrijft” interactive rebase geschiedenis. Dit betekent dat, wanneer u een reeks commits manipuleert met behulp van interactive rebase, dit deel van uw commithistorie zal herschreven worden: de commit’s SHA-1-hashes zullen veranderd zijn. Ze zijn volledig nieuwe commitobjecten, zo je wilt.

Dit feit roept een eenvoudige maar belangrijke regel op om te volgen: gebruik geen interactive rebase (of andere gereedschappen die geschiedenis herschrijven) op commits die u al met uw collega’s op een remote repository hebt gedeeld. Gebruik het in plaats daarvan om uw eigen, lokale commits op te schonen – zoals in een van uw eigen feature branches – voordat u ze samenvoegt in een team branch.

Het Basismechanisme van een Interactive Rebase Operatie

Hoewel er veel verschillende dingen zijn die interactive rebase kan worden gebruikt voor, is het basiswerkwijze altijd hetzelfde. Zodra u dit basismechanisme goed heeft begrepen, zal interactive rebase zijn lucht van “complexe mysterie” verliezen en een waardevol, toegankelijk item in uw gereedschapsbelt worden.

Stap 1: Waar moet u de sessie starten?

De eerste vraag die u moet beantwoorden is: “Welk deel van mijn commithistorie wil ik manipuleren?” Dit vertelt u waar u uw interactive rebase sessie moet starten. Laten we een praktisch voorbeeld nemen en zeggen dat we een oude commitbericht willen bewerken (wat we in feite zo meteen ook zullen doen).

Onze begintoestand is hieronder afgebeeld, waar we een oude commitbericht bewerken via interactieve rebase.

Om het commitbericht in C2 te kunnen wijzigen, moeten we onze interactieve rebase-sessie starten bij zijn oudercommit (of zelfs daarvoor, als je dat wilt). In dit voorbeeld gebruiken we C1 als startpunt voor onze interactieve rebase-sessie.

Stap 2: het starten van de eigenlijke sessie!

Het starten van de eigenlijke sessie is vrij eenvoudig:

$ git rebase -i HEAD~3

We gebruiken de git rebase opdracht met het -i vlaggetje (om aan te geven dat we het inderdaad “interactief” willen hebben) en geven de basiscommit door (die we in onze eerste stap hebben bedacht). In dit voorbeeld heb ik HEAD~3 gebruikt om de commit aan te geven die “3 achter de HEAD-commit” zit. Alternatief had ik ook een specifieke SHA-1 hash kunnen geven.

Stap 3: Git vertellen wat je wilt doen

Na het starten van de interactieve rebase-sessie, zie je een editor venster waar Git een reeks commits weergeeft – van de meest recente commit tot (maar niet inclusief) de commit die je als basiscommit hebt gekozen in Stap 1.

Er zijn twee belangrijke dingen om in gedachten te houden in deze stap:

  1. Commits worden in omgekeerde volgorde weergegeven! De nieuwste commit, die we zouden verwachten dat deze aan de top verschijnt, zal aan de bodem van de lijst verschijnen. Maak je geen zorgen: je Git repository is in topconditie! 🥳 Onthoud dat we bezig zijn met het uitvoeren van een interactieve rebase-operatie, en dit vereist dat Git de commits van oud naar nieuw op het einde van de operatie opnieuw toepast.
  2. Maak geen werkelijke wijzigingen in dit bewerkingsvenster! Hoewel je misschien wel willen gaan en de commitbericht in dit bewerkingsvenster aanpassen (immer, dat is wat we eigenlijk willen doen…), moet je wat geduld betrachten. Hier gaan we alleen vertellen Git wat we willen doen – maar niet de werkelijke verandering maken. Ik zal dit punt kort demonstreren!

Nu we deze theoretische overzicht hebben afgerond, laten we samen met enkele praktische gevallen duiken!

Bewerken van een oude commitbericht

Een van de zeer populaire gebruiksvoorbeelden van interactieve rebase is dat je een oude commitbericht na het feit kunt bewerken. Je bent misschien zich ervan bewust dat git commit --amend ook toestaat om een bericht van een commit te wijzigen – maar alleen als het de allerlaatste commit is. Voor elke commit ouder dan dat, moeten we interactieve rebase gebruiken!

Laten we een concreet scenario bekijken. Hieronder is een afbeelding van een slechte commitbericht die moet worden gecorrigeerd.

Opmerking: Voor een beter overzicht en duidelijker visualisatie, gebruik ik de Tower Git desktop client in sommige van mijn screenshots. Je hebt Tower niet nodig om mee te volgen in deze tutorial.

Voor ons voorbeeld, laten we zeggen dat we het bericht van de commit willen bewerken dat momenteel is getiteld “Optimaliseer mark-up structuur in index…”

Onze eerste stap is om de basiscommits te bepalen waarmee we deze interactieve rebase-sessie beginnen. Aangezien we (minstens) terug moeten gaan naar de ouder van onze “slechte appel” commit, beginnen we onze sessie bij HEAD~3 (drie commits achter de HEAD commit, die de commit is met de titel “Change headlines …”):

$ git rebase -i HEAD~3

Direct na het uitvoeren van deze opdracht, opent uw favoriete editor zich en presenteert de lijst met commits die u zojuist heeft geselecteerd (door een basiscommits te bieden).

Ter herinnering: hoewel u geneigd kunt zijn dit te doen, wij veranderen niet de commitberichten hier. We opmerken alleen de desbetreffende regel met een “actiewoord”. In ons geval willen we de commit herformuleren (wat betekent dat we het commitbericht willen wijzigen, maar de rest van de commit ongewijzigd willen laten).

Zeer praktisch zijn alle beschikbare actiewoorden gedocumenteerd onderaan dit venster – dus is er geen enkele reden om iets uit het hoofd te moeten onthouden!

Nadat u het standaard pick woord (wat “de commit zoals hij is aanvaarden” betekent) heeft vervangen door uw favoriete actiewoord, kunt u het venster gewoon opslaan en sluiten.

Daarna zal er een nieuw editorvenster openen dat het huidige commitbericht bevat. Eindelijk mogen we doen wat we in de eerste plaats wilden doen: het bericht van deze oude commit bewerken!

Na het aanbrengen van onze wijziging en vervolgens het opslaan en sluiten van het editorvenster, is de interactieve rebase-sessie compleet – en is ons commitbericht bijgewerkt! 🎉

Verwijderen van een ongewenste Commit

Interactive rebase biedt ook de mogelijkheid om verwijderen een oude commit uit uw geschiedenis die u niet meer nodig (of wilt) heeft. Stel je voor dat je per ongeluk een persoonlijk wachtwoord in een recente commit hebt opgenomen: gevoelige informatie zoals dit zou in de meeste gevallen niet in een codebase moeten worden opgenomen.

Vergeet ook niet dat het gewoon verwijderen van de informatie en opnieuw committen niet echt het probleem oplost: dit betekent dat het wachtwoord nog steeds in de repository is opgeslagen, in de vorm van je oude commit. Wat je echt wilt is deze stuk informatie netjes en volledig verwijderen uit de repository!

Laten we beginnen met het bepalen van de basiscommit voor onze interactieve rebase-sessie. Aangezien we minstens bij de ouder van de slechte commit moeten beginnen, gebruiken we de “Optimize markup structure…” commit als onze basis:

$ git rebase -i 6bcf266b

Merk op dat ik deze keer een concrete SHA-1 hash heb gebruikt in de git rebase -i opdracht. In plaats van de commit-hash had ik natuurlijk ook HEAD~2 kunnen gebruiken om die commit aan te spreken.

Na het uitvoeren van deze opdracht krijgen we weer een lijst met commits te zien.

Deze keer gebruiken we het drop actiewoord om de ongewenste commit kwijt te raken. In dit bijzondere geval kunnen we ook gewoon de hele regel uit de editor verwijderen. Als een regel (die een commit vertegenwoordigt) niet meer aanwezig is bij het opslaan en sluiten van het venster, zal Git de betreffende commit verwijderen.

Hoe je het ook aanpakt, na het opslaan en sluiten van het editorvenster, wordt de commit uit de geschiedenis van je repository verwijderd!

Het combineren van meerdere commits in één

Een ander gebruiksvoorbeeld voor interactieve rebase is wanneer je combineert meerdere afzonderlijke commits in één enkele. Voordat we in de diepte gaan over hoe dit werkt, laten we even stilstaan bij wanneer of waarom dit waardevol kan zijn.

Over het algemeen is het niet een goede strategie om commits “groter” te maken (door meerdere te combineren) in de meeste gevallen. De vuistregel is om commits zo klein mogelijk te houden, omdat “klein” betekent “makkelijker te lezen en te begrijpen”. Maar er zijn wel situaties waarin dit zinvol kan zijn. Hier zijn twee voorbeelden:

  • Stel dat je een probleem opmerkt in een oudere commit. Je zou dan een nieuwe commit kunnen maken die het probleem oplost. In zo’n situatie is het heel zinvol om deze commits in één te combineren: de nieuwere commit was immers slechts een “pleister” om een probleem op te lossen dat er in de eerste plaats niet had moeten zijn. Door deze commits te combineren, lijkt het alsof er nooit een probleem was geweest!
  • Een ander voorbeeld is wanneer je merkt dat je dingen een beetje te gedetailleerd hebt gemaakt. Kleine commits maken is prima, maar je commithistorie te bevuilen met veel onnodig kleine commits zou het doel te boven gaan.

De redenering is in beide voorbeelden hetzelfde: door twee (of meerdere) commits te combineren die in de eerste plaats één enkele hadden moeten zijn, produceer je een schonere en meer leesbare commithistorie!

Laten we samen een praktisch voorbeeld doornemen en de situatie hieronder als onze startsituatie beschouwen.

Laten we zeggen dat, semantisch gezien, het meer zin heeft dat deze twee commits één zijn. Met behulp van het squashen hulpmiddel van interactieve rebase, kunnen we ze inderdaad combineren:

$ git rebase -i HEAD~3

Op dit moment ben je al gewend aan wat er vervolgens gebeurt: een editor venster opent met een lijst van commits.

I already mentioned that we’re going to use the squash action keyword in this case. There’s an important thing to know about how squash works: the line you mark up with the keyword will be combined with the line directly above! This explains why I marked line 2 with the squash keyword in our example.

Na het opslaan en sluiten van dit venster, zal er een nieuw venster openen. Dit komt omdat, door meerdere commits te combineren, we natuurlijk een nieuwe maken. En deze heeft net als elke andere commit ook een commitbericht nodig!

Wat je in de bovenstaande schermafbeelding ziet, is wat Git voor ons heeft voorbereid: het heeft de commitberichten van de respectievelijke oorspronkelijke commits gecombineerd, samen met enkele opmerkingen. Je bent vrij om de oude berichten te verwijderen en opnieuw te beginnen – of ze te houden en extra informatie toe te voegen.

Na het opslaan en sluiten van dit editor venster, kunnen we met trots stellen: wat ooit twee afzonderlijke commits waren, is nu één!

De Kracht van Interactieve Rebase Inzetten

I hope you agree that Git’s interactive rebase tools can be very valuable! As developers, it’s important for us to strive for a clean and clear commit history. It’s a crucial ingredient in keeping a codebase healthy and easy to understand (both for your teammates, and yourself, after some time has passed).

Als je meer wilt leren, raad ik ten zeerste de “Eerstehulp Kit voor Git” aan. Het is een (gratis) verzameling van korte video’s die je leert hoe je in Git kunt opruimen en fouten ongedaan kunt maken.

Veel plezier!

Veel Gestelde Vragen (FAQs) over Git Interactieve Rebase

Wat is het verschil tussen Git Rebase en Git Merge?

Git Rebase en Git Merge zijn twee verschillende manieren om wijzigingen van één branch in een andere te integreren. Git Merge is een eenvoudige manier om code van twee verschillende branches te combineren. Het creëert een nieuwe commit in de geschiedenis, waarbij de chronologische volgorde van commits behouden blijft. Aan de andere kant is Git Rebase een manier om een reeks commits te verplaatsen of te combineren met een nieuwe basiscommit. Het is alsof je zegt: “Ik wil mijn wijzigingen baseren op wat iedereen anders heeft gedaan.” Met andere woorden, het stelt je in staat om de wijzigingen van de huidige branch bovenop een andere branch te plaatsen.

Hoe kan ik een Git Rebase ongedaan maken?

Als je een Git Rebase wilt ongedaan maken, kun je de opdracht git reflog gebruiken om de commit te vinden waarnaar je wilt terugkeren, en vervolgens de opdracht git reset --hard HEAD@{number} gebruiken. De git reflog opdracht toont een lijst van elke wijziging die aan de HEAD is aangebracht, en de git reset opdracht stelt je in staat om de huidige HEAD in te stellen op de opgegeven toestand.

Wat is het doel van Git Interactive Rebase?

Git Interactive Rebase stelt je in staat om commits op vele manieren te wijzigen, zoals bewerken, verwijderen en samenvoegen. Niet alleen kun je de commitberichten wijzigen, maar je kunt ook de eigenlijke code aanpassen als je een fout hebt gemaakt. Het is een krachtig hulpmiddel dat je volledige controle geeft over de commitgeschiedenis van je project.

Hoe kan ik commits samenvoegen met behulp van Git Interactive Rebase?

Het samenpersen is het gebeuren van het combineren van meerdere commits in één. In Git kun je commits samenpersen met behulp van de git rebase -i opdracht, gevolgd door de commit-hash die je wilt samenpersen. In de teksteditor die opent, kun je de commits die je wilt samenpersen markeren door pick te vervangen door squash of s naast elke commit.

Wat zijn de risico’s van het gebruik van Git Interactive Rebase?

Hoewel Git Interactive Rebase een krachtig hulpmiddel is, kan het gevaarlijk zijn als het niet correct wordt gebruikt. Het herschrijft commitgeschiedenis, wat problematisch kan zijn als je werkt aan een openbare branch waar anderen ook aan werken. Het wordt aanbevolen om het te gebruiken op lokale branches die nog niet zijn gepusht.

Hoe kan ik conflicten oplossen tijdens een Git Rebase?

Tijdens een rebase kunnen conflicten optreden. Git zal pauzeren en je toestaan om die conflicten op te lossen voordat het verdergaat. Je kunt conflicten oplossen door de bestanden aan te passen om de conflicterende wijzigingen te herstellen en vervolgens de opgeloste bestanden toe te voegen met git add. Na het oplossen van alle conflicten kun je de rebase voortzetten met git rebase --continue.

Kan ik Git Interactive Rebase gebruiken om een commit te splitsen?

Ja, je kunt Git Interactive Rebase gebruiken om een commit te splitsen in kleinere. Dit kan handig zijn als je meerdere wijzigingen in één commit hebt aangebracht, maar later besluit dat ze aparte commits hadden moeten zijn.

Hoe kan ik een commitbericht bewerken met behulp van Git Interactive Rebase?

Je kunt een commitbericht bewerken tijdens een interactieve rebase. In de lijst met committen, vervang pick door reword of r naast de commit die je wilt bewerken. Als je doorgaat, zal Git een teksteditor openen voor elke reword gemarkeerde commit, waardoor je het commitbericht kunt aanpassen.

Wat is het verschil tussen Git Rebase en Git Pull?

Git Pull is een opdracht die wijzigingen van een externe repository ophaalt en ze samenvoegt in je huidige branch. Aan de andere kant is Git Rebase een opdracht die een reeks committen verplaatst of combineert met een nieuwe basisset. Hoewel beide opdrachten worden gebruikt om wijzigingen te integreren, doen ze dat op verschillende manieren.

Kan ik Git Interactive Rebase gebruiken om de volgorde van committen te wijzigen?

Ja, je kunt de volgorde van committen wijzigen met behulp van Git Interactive Rebase. In de lijst met committen kun je gewoon de volgorde van de regels wijzigen om de volgorde van de committen te wijzigen. Dit kan handig zijn als je je commitgeschiedenis logischer of duidelijker wilt maken.

Source:
https://www.sitepoint.com/git-interactive-rebase-guide/