hetgit rebase commando heeft de reputatie magische Git voodoo te zijn waar beginners van weg zouden moeten blijven, maar het kan het leven veel gemakkelijker maken voor een ontwikkelteam als het voorzichtig gebruikt wordt. In dit artikel zullen we git rebase vergelijken met het gerelateerde git merge commando en alle mogelijke mogelijkheden identificeren om rebasen op te nemen in de typische Git workflow.,

conceptueel overzicht

het eerste wat je moet begrijpen over git rebase is dat het hetzelfde probleem oplost als git merge. Beide commando ‘ s zijn ontworpen om veranderingen van de ene branch naar de andere te integreren—ze doen het gewoon op heel verschillende manieren.

bedenk wat er gebeurt als je begint te werken aan een nieuwe functie in een dedicated branch, dan werkt een ander teamlid de master branch bij met nieuwe commits. Dit resulteert in een gevorkte geschiedenis, die bekend zou moeten zijn voor iedereen die Git als een collaboration tool heeft gebruikt.,

laten we nu zeggen dat de nieuwe commits in master relevant zijn voor de functie waar je aan werkt. Om de nieuwe commits op te nemen in je feature branch, heb je twee opties: mergen of rebasen.,

De Optie Samenvoegen

De eenvoudigste optie is het samenvoegen van de master tak in de ‘feature branch’ met iets als het volgende:

git checkout feature git merge master

Of u kunt comprimeren tot een one-liner:

 git merge feature master

Dit maakt een nieuwe “merge commit” in de feature tak die banden samen de geschiedenis van de beide takken, waardoor u een departementale structuur die er zo uit ziet:

Samenvoegen is mooi, want het is een niet-destructieve bewerking. De bestaande vestigingen worden op geen enkele manier gewijzigd., Dit voorkomt alle mogelijke valkuilen van rebasen (hieronder besproken).

aan de andere kant betekent dit ook dat de feature branch een vreemde merge commit zal hebben elke keer dat je upstream wijzigingen moet opnemen. Als master erg actief is, kan dit de geschiedenis van je feature branch behoorlijk vervuilen. Hoewel het mogelijk is om dit probleem te verhelpen met geavanceerde git log opties, kan het voor andere ontwikkelaars moeilijk worden om de geschiedenis van het project te begrijpen.,

de Rebase optie

als alternatief voor samenvoegen kunt u de feature tak rebasen op master tak met de volgende commando ‘ s:

git checkout feature git rebase master

Dit verplaatst de gehele feature branch om te beginnen op de punt van de master Branch, effectief alle nieuwe commits in master. Maar in plaats van een merge commit te gebruiken, schrijft rebasen de projectgeschiedenis opnieuw door gloednieuwe commits te maken voor elke commit in de oorspronkelijke branch.,

het grote voordeel van rebasen is dat je een veel schonere projectgeschiedenis krijgt. Ten eerste elimineert het de onnodige merge commits die vereist zijn door git merge. Ten tweede, zoals u kunt zien in het bovenstaande diagram, resulteert rebasen ook in een perfect lineaire projectgeschiedenis—u kunt de tip van feature volgen tot aan het begin van het project zonder vorken. Dit maakt het makkelijker om door uw project te navigeren met commando ‘ s als git log, git bisect, en gitk.,

maar er zijn twee afwegingen voor deze ongerepte commit geschiedenis: veiligheid en traceerbaarheid. Als u de gouden regel van Rebasen niet volgt, kan het herschrijven van projectgeschiedenis mogelijk catastrofaal zijn voor uw samenwerkingsworkflow. En, minder belangrijk, rebasen verliest de context die wordt geboden door een merge commit—je kunt niet zien wanneer upstream wijzigingen werden opgenomen in de functie.

interactief Rebasen

interactief rebasen geeft je de mogelijkheid om commits te wijzigen als ze naar de nieuwe branch worden verplaatst., Dit is nog krachtiger dan een geautomatiseerde rebase, omdat het volledige controle biedt over de commit historie van de branch. Meestal wordt dit gebruikt om een rommelige geschiedenis op te schonen voordat een feature branch wordt samengevoegd in master.,

om een interactieve rebase-sessie te beginnen, geef de optie i door aan de optie git rebase Commando:

git checkout feature git rebase -i master

Dit opent een teksteditor met alle commits die op het punt staan te worden verplaatst:

pick 33d5b7a Message for commit #1 pick 9480b3d Message for commit #2 pick 5c67e61 Message for commit #3

deze lijst definieert precies hoe de Branch eruit zal zien nadat de rebase is uitgevoerd. Door het pick commando te veranderen en/of de items opnieuw te ordenen, kun je de geschiedenis van de branch laten lijken op wat je wilt., Bijvoorbeeld, als de tweede commit een klein probleem in de eerste commit oplost, kun je ze condenseren tot een enkele commit met het fixup Commando:

pick 33d5b7a Message for commit #1 fixup 9480b3d Message for commit #2 pick 5c67e61 Message for commit #3

wanneer je het bestand opslaat en sluit, zal Git de rebase uitvoeren volgens jouw instructies, wat resulteert in projectgeschiedenis die er als volgt uitziet:

het elimineren van onbelangrijke commits zoals deze maakt de geschiedenis van je functie veel gemakkelijker te begrijpen. Dit is iets dat git merge gewoon niet kan doen.,

de gouden regel van Rebasen

als je eenmaal begrijpt wat rebasen is, is het belangrijkste om te leren wanneer je het niet moet doen. De gouden regel van git rebase is om het nooit te gebruiken op publieke branches.

denk bijvoorbeeld na over wat er zou gebeuren als je master op je feature branch:

De rebase verplaatst alle commits in master op de punt van feature. Het probleem is dat dit alleen in je repository gebeurde., Alle andere ontwikkelaars werken nog steeds met de originele master. Omdat rebasen resulteert in gloednieuwe commits, zal Git denken dat je master de geschiedenis van je branch is afgeweken van die van iedereen.

de enige manier om de twee master branches te synchroniseren is door ze weer samen te mergen, wat resulteert in een extra merge commit en twee sets van commits die dezelfde wijzigingen bevatten (de originele en die van je rebased branch). Onnodig te zeggen, Dit is een zeer verwarrende situatie.,

dus, voordat je git rebase uitvoert, vraag jezelf altijd af, “kijkt iemand anders naar deze branch?”Als het antwoord ja is, haal je handen van het toetsenbord en begin na te denken over een niet-destructieve manier om je wijzigingen aan te brengen (bijvoorbeeld het git revert Commando). Anders ben je veilig om de geschiedenis te herschrijven zoveel als je wilt.

Forceer

als je probeert de gerebaseerde master branch terug te pushen naar een remote repository, zal Git je verhinderen dit te doen omdat het conflicteert met de remote master branch., Maar je kunt de push forceren door de --force vlag te geven, zoals zo:

# Be very careful with this command! git push --force

Dit overschrijft de remote master branch om overeen te komen met de gerebased van je repository en maakt dingen erg verwarrend voor de rest van je team. Dus, wees heel voorzichtig om dit commando alleen te gebruiken als je precies weet wat je doet.

een van de enige keren dat je geforceerd moet pushen is wanneer je een lokale opruiming hebt uitgevoerd nadat je een private feature branch naar een remote repository hebt gepusht (bijvoorbeeld voor back-updoeleinden)., Dit is alsof je zegt: “Oeps, ik wilde niet echt die originele versie van de feature branch pushen. Neem in plaats daarvan de huidige.”Nogmaals, het is belangrijk dat niemand werkt van de commits van de originele versie van de feature branch.

Workflow Walkthrough

Rebasen kan in je bestaande Git workflow worden opgenomen zo veel of zo weinig als je team zich prettig voelt. In deze sectie zullen we kijken naar de voordelen die rebasen kan bieden in de verschillende stadia van de ontwikkeling van een functie.,

de eerste stap in elke workflow die gebruik maakt van git rebase is het maken van een speciale branch voor elke functie. Dit geeft u de benodigde branchstructuur om veilig rebasen te gebruiken:

Local Cleanup

een van de beste manieren om rebasen in uw workflow op te nemen is het opschonen van lokale, In-progress functies. Door periodiek een interactieve rebase uit te voeren, kun je ervoor zorgen dat elke commit in je functie gericht en zinvol is., Dit laat je je code schrijven zonder je zorgen te maken over het opsplitsen in geà soleerde commits—je kunt het achteraf repareren.

bij het aanroepen van git rebase, hebt u twee opties voor de nieuwe basis: de ouder-branch van de functie (bijvoorbeeld master), of een eerdere commit in uw functie. We zagen een voorbeeld van de eerste optie in de interactieve rebase sectie. De laatste optie is leuk als je alleen de laatste paar commits hoeft op te lossen. Bijvoorbeeld, het volgende commando start een interactieve rebase van alleen de laatste 3 commits.,

git checkout feature git rebase -i HEAD~3

door HEAD~3 op te geven als de nieuwe basis, verplaats je de branch niet echt—je herschrijft gewoon interactief de 3 commits die erop volgen. Merk op dat dit geen upstream wijzigingen zal opnemen in de feature branch.

Als u de hele functie met deze methode wilt herschrijven, kan de opdracht git merge-base nuttig zijn om de oorspronkelijke basis van de feature tak te vinden., Het volgende geeft de commit ID van de oorspronkelijke basis terug, die je vervolgens kunt doorgeven aan git rebase:

git merge-base feature master

dit gebruik van interactieve rebasen is een geweldige manier om git rebase in je workflow te introduceren, omdat het alleen lokale branches beïnvloedt. Het enige wat andere ontwikkelaars zullen zien is uw eindproduct, dat een schone, eenvoudig te volgen functie branch geschiedenis zou moeten zijn.

maar nogmaals, dit werkt alleen voor private feature branches., Als je samenwerkt met andere ontwikkelaars via dezelfde feature branch, is die branch openbaar en mag je de geschiedenis niet opnieuw schrijven.

er is geen git merge alternatief voor het opschonen van lokale commits met een interactieve rebase.

Upstream wijzigingen in een functie

in de sectie conceptueel overzicht zagen we hoe een feature-branch upstream wijzigingen van master kan opnemen met behulp van git merge of git rebase., Mergen is een veilige optie die de hele geschiedenis van je repository bewaart, terwijl rebasen een lineaire geschiedenis creëert door je feature branch naar de punt van masterte verplaatsen.

dit gebruik van git rebase is vergelijkbaar met een lokale opruiming (en kan gelijktijdig worden uitgevoerd), maar in het proces bevat het de upstream commits van master.

houd in gedachten dat het volkomen legaal is om te rebasen op een remote branch in plaats van master., Dit kan gebeuren wanneer je samenwerkt aan dezelfde functie met een andere ontwikkelaar en je moet hun wijzigingen in je repository opnemen.,

bijvoorbeeld, als u en een andere ontwikkelaar genaamd John toegevoegd, zich verbindt aan de feature tak, je archief kan er als volgt uitzien na het ophalen van de afstandsbediening feature tak van John ‘ s archief:

U kunt dit oplossen vork exact dezelfde manier als u een stroomopwaartse integratie van wijzigingen van master: ofwel het samenvoegen van uw plaatselijke feature met john/feature, of rebasen van uw plaatselijke feature op de tip van john/feature.,

merk op dat deze rebase niet in strijd is met de gouden regel van Rebasen omdat alleen uw lokale feature commits worden verplaatst—alles daarvoor is onaangeroerd. Dit is alsof je zegt: “voeg mijn veranderingen toe aan wat John al gedaan heeft.”In de meeste omstandigheden is dit intuïtiever dan synchroniseren met de remote branch via een merge commit.

standaard voert het commando git pull een samenvoeging uit, maar u kunt het forceren om de remote branch te integreren met een rebase door het de optie --rebase te geven.,

een functie met een Pull Request herzien

als je pull requests gebruikt als onderdeel van je code review proces, moet je vermijden git rebase te gebruiken na het aanmaken van de pull request. Zodra je de pull request doet, zullen andere ontwikkelaars naar je commits kijken, wat betekent dat het een publieke branch is. Het herschrijven van de geschiedenis zal het onmogelijk maken voor Git en je teamgenoten om follow-up commits te volgen die aan de functie zijn toegevoegd.

wijzigingen van andere ontwikkelaars moeten worden opgenomen met git merge in plaats van git rebase.,

om deze reden is het meestal een goed idee om je code op te schonen met een interactieve rebase voordat je je pull request instuurt.

integratie van een goedgekeurde functie

nadat een functie is goedgekeurd door uw team, hebt u de optie om de functie te rebasen op de punt van de master branch voordat u git merge gebruikt om de functie te integreren in de hoofdcodebasis.,

Dit is een vergelijkbare situatie als het opnemen van upstream wijzigingen in een feature branch, maar omdat je geen commits mag herschrijven in de master branch, moet je uiteindelijk git merge gebruiken om de feature te integreren. Echter, door een rebase uit te voeren voor de merge, ben je er zeker van dat de merge snel zal worden doorgestuurd, wat resulteert in een perfect lineaire geschiedenis. Dit geeft je ook de kans om follow-up commits die toegevoegd zijn tijdens een pull request te squashen.,

Als u niet helemaal vertrouwd bent met git rebase, kunt u de rebase altijd uitvoeren in een tijdelijke branch. Op die manier, als je per ongeluk de geschiedenis van je functie verknalt, kun je de originele branch bekijken en het opnieuw proberen. Bijvoorbeeld:

git checkout feature git checkout -b temporary-branch git rebase -i master # git checkout master git merge temporary-branch

samenvatting

en dat is alles wat je echt moet weten om te beginnen met rebasen van je branches., Als je de voorkeur geeft aan een schone, lineaire geschiedenis zonder onnodige merge commits, moet je git rebase bereiken in plaats van git merge bij het integreren van wijzigingen van een andere branch.

aan de andere kant, als je de volledige geschiedenis van je project wilt behouden en het risico wilt vermijden dat publieke commits opnieuw worden geschreven, kun je git mergegebruiken. Beide opties zijn perfect geldig, maar nu heb je tenminste de optie om gebruik te maken van de voordelen van git rebase.