Als je al een tijdje met Git werkt, ben je waarschijnlijk wel eens een geschiedenis tegengekomen vol nutteloze commits, "WIP"-berichten, snelle tests of zelfs lege commits die alleen maar zijn aangemaakt om een āāhook of pipeline te activeren. Op dat moment kijk je naar het logboek en denk je: āNiemand kan dit begrijpenāHet goede nieuws is dat je niet alleen bent: het overkomt ons allemaal, en daar is ondersteuning voor. git rebasen.
Het interessante is dat, mits correct gebruikt, Met git rebase kun je de commitgeschiedenis 'opschonen'.Maak het lineair, ruisvrij en veel gemakkelijker te controleren. Je kunt testcommits verwijderen, meerdere commits samenvoegen tot ƩƩn, ze opnieuw ordenen, commitberichten corrigeren en zelfs wijzigingen van de remote repository verwijderen via een geforceerde push. Laten we aan de hand van concrete voorbeelden bekijken hoe je rebase kunt gebruiken om je geschiedenis van totale chaos om te toveren tot iets georganiseerds en leesbaars.
Wat is Git Rebase precies en waarom heeft het invloed op de geschiedenis?
Als we het over inhalen hebben, hebben we het letterlijk over inhalen. het beginpunt van een tak wijzigenGit neemt de commits van je branch en "reproduceert" ze ƩƩn voor ƩƩn op een andere basis (meestal de branch). hoofd- of een bijgewerkte externe branch). Het is alsof je terug in de tijd bent gegaan en je werk vanaf een andere commit bent begonnen, maar de wijzigingen hebt behouden.
Stel je voor dat je project dit verhaal in de hoofdbranch heeft: A ā B ā CJe maakt een functionele tak aan en voert vervolgens twee commits uit: D - EOndertussen voegt iemand in de hoofdbranch een nieuwe commit toe. FZonder een nieuwe basis te creĆ«ren, zouden je branches er ongeveer zo uitzien:
A---B---C---F (main)
A---B---C---D---E (feature)
Als je een klassieke merge uitvoert van je feature branch naar main, krijg je een extra merge commit, die vaak het volgende genereert: ingewikkelde geschiedenis met meerdere gekruiste lijnen. Bij rebase daarentegen neemt Git je commits D en E en past ze opnieuw toe op F:
A---B---C---F---D'---E' (feature reescrita)
die D' en E' Dit zijn niet precies dezelfde commits als D en E: het zijn "kopieƫn" met nieuwe identificatoren (hashes). Daarom zeggen we rebase. herschrijft de geschiedenisHet resultaat is een lineairder logboek, zonder tussentijdse samenvoegingscommits die alleen maar ruis toevoegen.

Waarom je een schone commitgeschiedenis zou moeten hebben
Een geordende administratie is niet alleen een kwestie van esthetiek. Een overzichtelijk logboek maakt het dagelijkse werk een stuk gemakkelijker.Je kunt in ƩƩn oogopslag zien wat er is gedaan, wanneer en waarom, zonder dat je door lege merge-commits of contextloze "snelle oplossing"-berichten hoeft te bladeren.
Wanneer branches worden samengevoegd door constant vanuit de hoofdbranch te mergen, krijg je uiteindelijk een heleboel commits zoals "Merge branch 'main' into feature-x" die Ze geven geen betrouwbare informatie over codewijzigingen.Dit maakt taken zoals de volgende complexer:
- Zoek de commit waarin een bug is geĆÆntroduceerd met behulp van hulpmiddelen voor het vergelijken van bestandenomdat de geschiedenis vol zit met irrelevante fusies.
- Bekijk pull-aanvragenomdat je tussen overbodige commits moet schakelen om te zien wat er daadwerkelijk is veranderd.
- Inzicht in de evolutie van een kenmerkvooral als het is ontwikkeld via veel kleine testcommits.
Git rebase is het ideale hulpmiddel om al die ruis te "polijsten" voordat je de branch met de rest van het team deelt. Het is alsof je je hele geschiedenis in de wasmachine stopt.Je houdt de belangrijkste wijzigingen overzichtelijk bij elkaar, goed gegroepeerd en met duidelijke boodschappen.
Belangrijkste verschillen tussen git merge en git rebase
Om volledig te begrijpen wat je doet wanneer je rebase gebruikt, is het de moeite waard om het gedrag ervan te vergelijken met dat van git samenvoegenBeide methoden dienen om veranderingen te integreren, maar op verschillende manieren en met belangrijke gevolgen voor de geschiedenis.
met samensmeltenGit maakt een nieuwe merge-commit aan met twee ouders: de tip van je eigen branch en de tip van de branch waarmee je samenvoegt. De resulterende geschiedenis behoudt exact de oorspronkelijke volgorde van commitsMaar het kan uiteindelijk vol komen te zitten met parallelle vertakkingen en samenvoegingen.
met opnieuw baserenIn plaats van een merge-commit te maken, neemt Git je commits en past ze ƩƩn voor ƩƩn toe op de nieuwe database. Dit genereert... nieuwe commits met nieuwe hasheszelfs als de codewijzigingen hetzelfde zijn.
In praktijk:
- gaan Het bewaart de geschiedenis precies zoals die zich heeft afgespeeld, met alle onderlinge verbanden en samenvoegingen.
- rebase Het genereert een lineaire en overzichtelijke geschiedenis, alsof alles zich in een rechte lijn heeft afgespeeld.
De keuze is niet "de ene is beter dan de andere", maar Voor welke situatie is elk van beide het meest geschikt?Om reeds gedeelde en gesloten branches te combineren, is samenvoegen (mergen) meestal de veiligste optie. Om lokale werkbranches georganiseerd te houden of voordat een pull request wordt geopend, is rebase een uitstekende keuze.

Situaties waarin rebase uitblinkt: het bijwerken en optimaliseren van branches
Er zijn twee scenario's waarin de meeste ontwikkelaars dagelijks rebase gebruiken: Houd uw werkfiliaal op de hoogte van de laatste ontwikkelingen. y Ruim commits op voordat je ze deelt.Laten we ze eens nader bekijken.
Werk je feature-branch bij met de nieuwste wijzigingen van de hoofdbranch.
Je werkt aan een nieuwe functie in je branch, maar ondertussen zijn je collega's nog steeds bezig met commits in een andere branch. hoofd-Als je je wijzigingen wilt integreren, kun je het volgende doen:
git checkout tu-rama-feature
git merge main
Dit werkt, maar het genereert elke keer dat je synchroniseert een merge-commit, wat uiteindelijk problemen veroorzaakt. een geschiedenis vol herhalende fusiesMaar als je dat wel doet:
git checkout tu-rama-feature
git rebase main
Git verplaatst je commits bovenop de laatste status van main, alsof je de branch na die wijzigingen was begonnen. Je krijgt dan... een lineaire geschiedenis, zonder tussentijdse merge-commitsen de beoordeling zal duidelijker zijn.
Maak je commits schoon voordat je een pull request opent.
Het komt vaak voor dat je tijdens de ontwikkeling van een functie commits hebt zoals "typefout gecorrigeerd", "pipeline testen", "meer wijzigingen in de login", enzovoort. Dat is prima zolang je aan het werk bent, maar Dat is niet het soort geschiedenis dat je wilt laten zien. wanneer je een pull request opent.
Met interactieve rebase kunt u reorganiseer en groepeer die commits in iets logischer. Bijvoorbeeld, in plaats van dit:
- WIP: aƱadir login
- MƔs cambios login
- Corregir tests login
- Arreglar typo variable
Je kunt uiteindelijk ƩƩn enkele, goed beschreven commit overhouden:
- AƱadir funcionalidad completa de login de usuario con tests
Die "opschoning" van de geschiedenis maakt het voor recensenten veel gemakkelijker om het te begrijpen. wat elke commit bijdraagt en vereenvoudigt het oplossen van problemen in de toekomst.
Interactieve rebase om de geschiedenis te herschrijven
De basisversie van rebase verplaatst je commits simpelweg naar een andere basis. Maar het pronkstuk is de interactieve overbase, waarmee een editor wordt geopend met een lijst van recente commits, zodat je kunt beslissen wat je met elk ervan wilt doen.
De gebruikelijke manier om hiermee te beginnen is door aan te geven hoeveel commits terug je wilt "touchen" vanaf je huidige HEAD. Bijvoorbeeld:
git rebase -i HEAD~6
Met dit commando zeg je tegen Git: "Neem de laatste 6 commits van deze branch en bereid een interactieve rebase voor." Git opent dan je standaardeditor (Vim, Nano, VS Code, enz.) met iets als:
pick 7ed9c6e update version
pick ecb7ef3 empty commit 1
pick a323615 empty commit 2
pick 2c3d41d empty commit 3
pick d53c00f empty commit 4
pick 22dcc79 empty commit 5
# Herbaseer 549dd76..22dcc79 naar 549dd76 (6 commando's)
#
# Commando's:
# p, kies = gebruik commit
# r, herformuleren = Gebruik commit, maar bewerk het bericht
# e, bewerken = Gebruik commit en stop om het te wijzigen
# s, squash = samenvoegen met de vorige commit
# f, fixup = zoals squash, maar dan zonder het bericht
# x, uitvoeren = shell-opdracht uitvoeren
# b, break = stop rebase hier
# d, drop = commit verwijderen
ā
Let op ƩƩn belangrijk detail: De volgorde in dit bestand is omgekeerd aan wat je in het git-logbestand ziet.In het bestand is de eerstgenoemde commit (7ed9c6e) de oudste van de zes, en de laatste (22dcc79) de meest recente. Dit is belangrijk om verwarring te voorkomen wanneer je commits verwijdert of de volgorde ervan wijzigt.
Verwijder testcommits of lege commits uit de lokale geschiedenis.
Stel dat je, om een āāGit-hook te testen, lege commits hebt gemaakt met de optie ā leeg laten. Bijvoorbeeld:
git commit -m "commit with no changes" --allow-empty
Met deze optie kun je een commit maken, zelfs als er geen wijzigingen in de bestanden zijn, wat handig is voor testdoeleinden. Het vervuilt de geschiedenis met commits die geen echte waarde hebben.Stel je voor dat je logboek er zo uitziet:
git log --pretty=oneline --abbrev-commit
En wat je krijgt:
22dcc79 (HEAD -> main, origin/main, origin/HEAD) empty commit 5
d53c00f empty commit 4
2c3d41d empty commit 3
a323615 empty commit 2
ecb7ef3 empty commit 1
7ed9c6e update version
In dit scenario wilt u alleen de nuttige commit "updateversie" behouden en alle andere verwijderen. lege commit Dit waren slechts tests. Om dit te doen, voer je de interactieve rebase uit op de laatste 6 commits:
git rebase -i HEAD~6
De editor opent met de 6 commits. Je doel is om de regels te verwijderen die overeenkomen met de lege commits. Je wilt dus alleen zoiets overhouden:
pick 7ed9c6e update version
# Herbaseer 549dd76..22dcc79 naar 549dd76 (6 commando's)
# ⦠rest van de reacties ā¦
Zoals aangegeven in de helpsectie van het bestand zelf, Als je een regel verwijdert, verdwijnt die commit uit de geschiedenis. In de nieuwe, herschreven versie zal Git bij het opslaan en sluiten van de editor alleen de commit "update version" reproduceren en de andere commits negeren.
Het nieuwe verhaal uploaden naar Origin: gebruikmaken van een geforceerde push
Tot nu toe zijn alle rebase-wijzigingen doorgevoerd in uw lokale kopie van de repository. Als u wilt dat deze opschoning ook wordt doorgevoerd in de externe repository (bijvoorbeeld in de repository zelf), kunt u dat doen via de optie 'rebase'. oorsprong/hoofd), moet u de externe geschiedenis overschrijven met de nieuwe.
Dit wordt gedaan met een geforceerde duwEen gebruikelijke manier om dit aan te geven is door het plusteken (+) voor de branchenaam te plaatsen bij het pushen:
git push origin +main
Dat plusteken vertelt Git dat Negeer de afwijking in de geschiedenis en overschrijf de externe branch. met jouw herschreven versie. Als je simpelweg probeerde het volgende te doen:
git push origin main
Git zou je waarschuwen dat je lokale geschiedenis geen directe afstammeling is van de externe geschiedenis (omdat je commits hebt herschreven met rebase) en zou de push weigeren om gegevensverlies te voorkomen.
Het is belangrijk te begrijpen dat, na deze gedwongen verplaatsing, Verwijderde commits zijn niet langer toegankelijk vanuit origin/main.Ze kunnen nog steeds voorkomen in herarchieven of lokale kopieƫn van andere collega's, maar in de praktijk hebt u de archiefgeschiedenis gewist.
Ernstige waarschuwing: het herschrijven van gedeelde branches is geen spelletje.
Het herschrijven van de geschiedenis klinkt geweldig om alles te ordenen, maar het heeft een belangrijk gevolg: bij het aanmaken van nieuwe commits met nieuwe hashes, Je gooit iedereen overhoop die zijn werk al op de oude commits had gebaseerd.Daarom bestaat de beroemde gouden regel:
Rebase geen branches die al gedeeld worden en actief door anderen worden gebruikt.
In de praktijk betekent dit dat het veilig is om rebase te gebruiken op:
- Lokale kenmerkende takken die je nog niet hebt gepubliceerd of die alleen jij gebruikt.
- Recente toezeggingen Diegenen waarvan je weet dat niemand anders er nog van afhankelijk is.
En het is een behoorlijk slecht idee om dat te doen:
- hoofd-, ontwikkelings- of een andere "officiƫle" tak uit de database die als basis dient voor meerdere personen.
- Gedeelde werkafdelingen waarbij meer dan ƩƩn ontwikkelaar commits maakt.
Als je de geschiedenis van een gedeelde branch herschrijft en vervolgens een geforceerde push uitvoert, zullen andere teamleden merken dat... De vertakkingen verwijzen naar commits die niet langer bestaan āāin de externe repository.Ze zullen meer geavanceerde bewerkingen moeten uitvoeren (zoals het opnieuw baseren op de nieuwe geschiedenis of het resetten) om de puinhoop op te ruimen.
Duwkracht: beter met een veiligheidsgordel
In veel gevallen moet je na een rebase een push forceren. De klassieke optie is:
git push --force origin tu-rama
Deze variant overschrijft echter alles op de externe schijf zonder toestemming. Om te voorkomen dat je per ongeluk andermans werk overschrijft, biedt Git een veel betere optie: āforce-with-lease.
Wanneer je dat doet:
git push --force-with-lease origin tu-rama
Git controleert eerst dat De afstandsbediening is nog steeds in de staat waarin je hem aantrof. Wanneer je je laatste pull of fetch hebt uitgevoerd. Als het systeem detecteert dat iemand sindsdien nieuwe commits naar die branch heeft gepusht, wordt de push geweigerd en niet geforceerd. Zo voorkom je dat je de wijzigingen van anderen overschrijft.
Het idee is om rebase en force push te combineren, altijd met een koel hoofd: alleen in branches die u beheert en, waar mogelijk, gebruikmaken van āforce-with-lease als extra beveiligingslaag.
Wat te doen als een rebase mislukt: reflog biedt uitkomst.
Het is ons allemaal wel eens overkomen: je start een interactieve rebase, verwijdert of wijzigt per ongeluk iets, lost een conflict verkeerd op en plotseling... Het lijkt erop dat je een deel van je baan bent kwijtgeraakt.Voordat je in paniek raakt, onthoud dat Git nog een troef achter de hand heeft: git reflog.
De reflog is een lokaal overzicht van alle HEAD-bewegingen: nieuwe commits, resets, rebases, merges, enz. Dankzij de reflog kun je de locatie van je branch achterhalen voordat je de fout inging en met een harde reset naar dat punt terugkeren.
De typische stroom zou zijn:
git reflog
Daar ziet u een lijst met vermeldingen die er ongeveer zo uitziet:
abc1234 HEAD@{0}: rebase terminado
def5678 HEAD@{1}: checkout: moving from main to main
...
Je geeft aan bij welke commit je was voordat je de rebase startte (bijvoorbeeld, zeker5678) en je gaat naar hem terug met:
git reset --hard def5678
Op deze manier Je verwijdert de overlay volledig. en je keert terug naar de vorige staat. Je kunt een lopende rebase ook afbreken (als je midden in het proces zit en het nog niet hebt afgerond) met:
git rebase --abort
Met dit commando blijft je branch zoals hij was vlak voordat de huidige rebase begon. Dit is ideaal wanneer er conflicten ontstaan āādie je niet wilt, of wanneer je ziet dat het geen goed moment is om verder te gaan.
Git pull versus git pull ārebase: kleine verschillen, grote impact
Een ander punt dat vaak tot twijfels leidt, is het verschil tussen git pull normaal en git pull --rebaseBeide systemen werken uw lokale vestiging bij vanuit de externe locatie, maar ze doen dat op verschillende manieren.
Wanneer je het volgende uitvoert:
git pull
Git doorloopt twee stappen: git ophalen om de wijzigingen van de afstandsbediening over te nemen en vervolgens een git samenvoegen om ze te combineren met je huidige branch. Dit kan een extra merge commit creƫren als je lokale commits boven de remote commit hebt staan, wat opnieuw geschiedenis met onnodige samenvoegingen.
Als je echter het volgende uitvoert:
git pull --rebase
Git voert de fetch uit en vervolgens Kopieer je lokale commits naar de bijgewerkte versie op de externe server.Het resultaat is vergelijkbaar met wat je zou hebben gedaan. git fetch gevolgd door git rebase origin/mainen zorgt voor een duidelijkere, meer lineaire geschiedenis.
Daarom configureren veel teams Git standaard zo dat het rebase gebruikt bij het maken van pulls. Het is een eenvoudige manier om automatische samenvoegingscommits vermijden die niet veel bijdragen.
Bestanden of afbeeldingen uit de geschiedenis verwijderen: algemeen idee
Soms is het probleem niet een lelijke commit, maar een bestand dat nooit in de repository terecht had mogen komenEen verkeerde afbeelding, onjuiste inloggegevens, enorme bestanden, enzovoort. De verleiding is groot om naar GitHub te gaan en naar het prullenbakpictogram te zoeken, maar als dat is uitgeschakeld en berichten weergeeft zoals "je moet op een branch zitten", dan komt dat doordat... GitHub staat niet toe dat je de geschiedenis op die manier verwijdert..
De juiste manier houdt meestal in dat je de geschiedenis herschrijft vanaf je lokale machine (met interactieve rebase of tools zoals...). git filter repository) en voer vervolgens een geforceerde push uit. In GitHub Desktop kun je ook branches en commits beheren, maar de werking van Een bestand volledig verwijderen uit alle commits Dit houdt in dat de geschiedenis op een vergelijkbare manier wordt herschreven als wat we hier zien gebeuren.
Kortom, als je de verkeerde afbeelding of een gevoelig bestand uploadt en je wilt dat het uit de geschiedenis verdwijnt, is het simpelweg verwijderen ervan in de laatste commit niet voldoende: De commits waarin dit werd geĆÆntroduceerd, moeten worden herschreven. En dan de duw forceren. Het is een delicate operatie en moet rustig en in overleg met je team worden uitgevoerd.
Praktische oefening om inhalen te oefenen zonder iets te beschadigen.
De beste manier om bedreven te raken in het inhalen is door te oefenen in een gecontroleerde omgeving, zonder bang te hoeven zijn om andermans werk te verstoren. Een eenvoudig voorbeeld is:
- Maak een nieuwe branch aan vanuit de hoofdbranch met git checkout -b my-tests-branch.
- Maak een aantal kleine commits (dit kunnen triviale wijzigingen of testbestanden zijn).
- Simuleer de voortgang van de main-branch door daar nieuwe commits te maken (of iemand anders te vragen dit te doen).
- Ga terug naar je testbranch en voer de volgende opdracht uit. git rebase main om te zien hoe je commits worden verplaatst.
- probeer eens git rebase -i HEAD~3 Om de meest recente commits samen te voegen, te hernoemen of te verwijderen.
Met deze oefening zul je zien hoe Wijzig de geschiedenis ervoor en erna.Hoe Git omgaat met conflicten en hoe je indien nodig met reflog kunt terugkeren naar eerdere statussen. Hoe meer je lokaal oefent, hoe meer zelfvertrouwen je krijgt bij het toepassen van deze technieken op echte projectbranches.
Door Git rebase onder de knie te krijgen, kun je een chaotische geschiedenis, vol lege commits, onnodige merges en betekenisloze berichten, omzetten in een duidelijke en leesbare reeks belangrijke wijzigingen. Door interactieve rebase te gebruiken, testcommits te verwijderen, verspreid werk te groeperen, branches lineair bij te werken en te vertrouwen op tools zoals reflog en geforceerde pushes met `--force-with-lease`, kun je je repository in een veel gezondere en professionelere staat houden. Zorg er wel voor dat je deze technieken alleen toepast op branches die onder jouw controle staan āāen dat je het team op de hoogte stelt voordat je de gedeelde geschiedenis herschrijft.