kommandotgit rebase
har ett rykte om att vara magisk Git voodoo som nybörjare borde hålla sig borta från, men det kan faktiskt göra livet mycket lättare för ett utvecklingsteam när det används med försiktighet. I den här artikeln jämför vi git rebase
med kommandot git merge
och identifierar alla potentiella möjligheter att införliva rebasering i det typiska Git-arbetsflödet.,
konceptuell översikt
det första att förstå omgit rebase
är att det löser samma problem somgit merge
. Båda dessa kommandon är utformade för att integrera förändringar från en gren till en annan gren—de gör det bara på mycket olika sätt.
Tänk på vad som händer när du börjar arbeta med en ny funktion i en dedikerad gren, sedan en annan gruppmedlem uppdaterarmaster
gren med nya åtaganden. Detta resulterar i en forked historia, som bör vara bekant för alla som har använt Git som ett samarbetsverktyg.,
nu, låt oss säga att den nya förbinder sig imaster
är relevanta för funktionen som du arbetar med. För att införliva de nya åtagandena i din feature
– gren har du två alternativ: sammanslagning eller ombokning.,
Kopplingsalternativet
det enklaste alternativet är att slå sammanmaster
-grenen i funktionsgrenen med något som följer:
git checkout feature git merge master
eller så kan du kondensera detta till en one-liner:
git merge feature master
det här skapar en ny ”merge commit” i”. denfeature
gren som knyter samman historierna av båda grenarna, vilket ger dig en gren struktur som ser ut så här:
sammanslagning är trevligt eftersom det är en icke-förstörande operation. De befintliga grenarna ändras inte på något sätt., Detta undviker alla potentiella fallgropar i rebasing (diskuteras nedan).
å andra sidan betyder det också attfeature
– grenen kommer att ha en extern sammanslagning varje gång du behöver införliva uppströmsändringar. Ommaster
är mycket aktiv kan detta förorena funktionen grenens historia ganska lite. Även om det är möjligt att mildra problemet med avancerade git log
alternativ, kan det göra det svårt för andra utvecklare att förstå projektets historia.,
alternativet Rebase
som ett alternativ till att slå samman kan du göra omfeature
– filialen tillmaster
– filialen med följande kommandon:
git checkout feature git rebase master
detta flyttar helafeature
– filialen till att börja på spetsen av grenen.master
gren, effektivt införliva alla nya åtaganden imaster
. Men istället för att använda en sammanslagningskommission skriver rebasing om projekthistoriken genom att skapa helt nya åtaganden för varje åtagande i den ursprungliga grenen.,
den största fördelen med att rebasera är att du får en mycket renare projekthistorik. För det första eliminerar den onödiga sammanslagningen begår som krävs av git merge
. För det andra, som du kan se i ovanstående diagram, resulterar rebasering också i en perfekt linjär projekthistoria—du kan följa spetsen på feature
hela vägen till början av projektet utan gafflar. Detta gör det lättare att navigera i projektet med kommandon som git log
, git bisect
och gitk
.,
men det finns två kompromisser för denna orörda begå historia: säkerhet och spårbarhet. Om du inte följer den gyllene regeln om Rebasing, kan re-writing projekthistorik vara potentiellt katastrofala för ditt samarbete arbetsflöde. Och, mindre viktigt, rebasing förlorar sammanhanget som tillhandahålls av en merge commit – du kan inte se när uppströmsändringar införlivades i funktionen.
interaktiv Rebasering
interaktiv rebasering ger Dig möjlighet att ändra åtaganden när de flyttas till den nya grenen., Detta är ännu kraftfullare än en automatiserad rebase, eftersom det erbjuder fullständig kontroll över filialens begå historia. Vanligtvis används detta för att rensa upp en rörig historia innan du slår samman en funktion gren i master
.,
för att starta en interaktiv rebaseringssession, skickai
– alternativet till kommandotgit rebase
:
git checkout feature git rebase -i master
det här öppnar en textredigerare som listar alla åtaganden som ska flyttas:
pick 33d5b7a Message for commit #1 pick 9480b3d Message for commit #2 pick 5c67e61 Message for commit #3
denna lista definierar exakt hur grenen kommer att se ut efter rebase utförs. Genom att ändra kommandotpick
och/eller ombeställa posterna kan du få filialens Historik att se ut som vad du vill., Till exempel, om 2: a begå åtgärdar ett litet problem i 1: A begå, du kan kondensera dem till en enda begå med kommandot fixup
:
pick 33d5b7a Message for commit #1 fixup 9480b3d Message for commit #2 pick 5c67e61 Message for commit #3
När du sparar och stänger filen, Git kommer att utföra rebase enligt dina instruktioner, vilket resulterar i projekthistorik som ser ut som följande:
eliminera obetydliga begår som detta gör din funktion historia mycket lättare att förstå. Detta är något som git merge
helt enkelt inte kan göra.,
den gyllene regeln för Rebasing
När du förstår vad rebasing är, är det viktigaste att lära sig när man inte ska göra det. Den gyllene regeln för git rebase
är att aldrig använda den på offentliga grenar.
tänk till exempel på vad som skulle hända om du rebaserademaster
på dinfeature
gren:
rebasen flyttar alla åtaganden imaster
på spetsen avfeature
. Problemet är att detta bara hände i ditt förråd., Alla andra utvecklare arbetar fortfarande med den ursprungliga master
. Eftersom rebasering resulterar i helt nya åtaganden, Git kommer att tro att din master
grenens historia har avvikit från alla andras.
det enda sättet att synkronisera de två master
grenar är att slå samman dem tillbaka tillsammans, vilket resulterar i en extra sammanfogning begå och två uppsättningar av åtaganden som innehåller samma ändringar (de ursprungliga, och de från din rebased gren). Naturligtvis är detta en mycket förvirrande situation.,
så, innan du körgit rebase
, fråga dig själv, ”är det någon annan som tittar på den här grenen?”Om svaret är ja, ta bort händerna från tangentbordet och börja tänka på ett icke-destruktivt sätt att göra dina ändringar (t.ex. kommandot git revert
). Annars är du säker på att skriva om historia så mycket du vill.
Force-Pushing
om du försöker trycka på rebasedmaster
gren tillbaka till ett fjärrförråd, kommer Git hindra dig från att göra det eftersom det strider mot fjärrkontrollenmaster
gren., Men du kan tvinga push att gå igenom genom att skicka --force
– flaggan, så här:
# Be very careful with this command! git push --force
det här skriver över fjärren master
– grenen för att matcha den rebaserade från ditt förråd och gör saker väldigt förvirrande för resten av ditt lag. Så var försiktig så att du bara använder det här kommandot när du vet exakt vad du gör.
en av de enda gångerna du ska trycka på är när du har utfört en lokal rensning efter att du har tryckt en privat funktion gren till ett fjärrförråd (t.ex. för säkerhetskopiering)., Det här är som att säga, ” Oj, jag ville inte verkligen driva den ursprungliga versionen av funktionsgrenen. Ta den nuvarande istället.”Återigen är det viktigt att ingen arbetar av begår från den ursprungliga versionen av funktionen gren.
Workflow Walkthrough
Rebasing kan införlivas i ditt befintliga git-arbetsflöde så mycket eller så lite som ditt lag är bekvämt med. I det här avsnittet tar vi en titt på de fördelar som rebasing kan erbjuda i de olika stadierna av en funktions utveckling.,
det första steget i ett arbetsflöde som utnyttjar git rebase
är att skapa en dedikerad gren för varje funktion. Detta ger dig den nödvändiga grenstrukturen för att säkert använda rebasing:
lokal rensning
ett av de bästa sätten att införliva rebasing i ditt arbetsflöde är att städa upp lokala, pågående funktioner. Genom att regelbundet utföra en interaktiv rebase, kan du se till att varje begå i din funktion är fokuserad och meningsfull., Detta låter dig skriva din kod utan att oroa dig för att bryta upp det i isolerade begår – du kan fixa det efter faktum.
När du anropar git rebase
har du två alternativ för den nya basen: featurens överordnade gren (t.ex. master
), eller ett tidigare åtagande i din funktion. Vi såg ett exempel på det första alternativet i den interaktiva Rebasing sektionen. Det senare alternativet är trevligt när du bara behöver fixa de sista begå. Till exempel börjar följande kommando en interaktiv rebase av endast de senaste 3 begår.,
git checkout feature git rebase -i HEAD~3
genom att angeHEAD~3
som den nya basen flyttar du faktiskt inte grenen—du skriver bara interaktivt om de 3 begår som följer den. Observera att detta inte kommer att införliva uppströmsändringar i feature
– grenen.
om du vill skriva om hela funktionen med den här metoden kan kommandotgit merge-base
vara användbart för att hitta den ursprungliga basen för grenenfeature
., Följande returnerar begå-ID för den ursprungliga basen, som du sedan kan skicka till git rebase
:
git merge-base feature master
denna användning av interaktiv rebasering är ett bra sätt att introducera git rebase
I ditt arbetsflöde, eftersom det bara påverkar lokala grenar. Det enda andra utvecklare kommer att se är din färdiga produkt, som bör vara en ren, lätt att följa funktionen gren historia.
men igen fungerar det bara för privata funktionskontor., Om du samarbetar med andra utvecklare via samma funktionsgren är den grenen offentlig och du får inte skriva om dess historia.
det finns ingengit merge
alternativ för att städa upp lokala åtaganden med en interaktiv rebase.
införliva Uppströmsändringar i en funktion
i avsnittet konceptuell översikt såg vi hur en funktion gren kan införliva uppströms förändringar frånmaster
använda antingengit merge
ellergit rebase
., Sammanslagning är ett säkert alternativ som bevarar hela historiken i ditt förråd, medan ombokning skapar en linjär historia genom att flytta din funktion gren på spetsen av master
.
denna användning av git rebase
liknar en lokal rensning (och kan utföras samtidigt), men i processen ingår de uppströms begår från master
.
Kom ihåg att det är helt lagligt att byta till en fjärravdelning istället för master
., Detta kan hända när du samarbetar på samma funktion med en annan utvecklare och du måste införliva sina ändringar i ditt förråd.,
till exempel, om du och en annan utvecklare som heter John added förbinder sig till grenen feature
kan ditt förråd se ut som följande efter att ha hämtat fjärrkontrollen feature
från Johns förråd:
Du kan lösa denna gaffel på exakt samma sätt som du integrerar uppströmsändringar från master
: antingen slå samman din lokala feature
med john/feature
, eller rebase din lokala feature
på spetsen av john/feature
.,
Observera att denna rebase inte bryter mot den gyllene regeln om Rebasering eftersom endast dina lokalafeature
åtaganden flyttas—allt innan det är orört. Det här är som att säga: ”lägg till mina ändringar i vad John redan har gjort.”Under de flesta omständigheter är detta mer intuitivt än att synkronisera med fjärrgrenen via en sammanslagningskommission.
som standard utför kommandotgit pull
en sammanfogning, men du kan tvinga den att integrera fjärrgrenen med ett rebase genom att skicka det alternativet--rebase
.,
granska en funktion med en Pull Request
om du använder pull request som en del av din kodöversynsprocess måste du undvika att användagit rebase
efter att du skapat pull request. Så fort du gör pull-förfrågan kommer andra utvecklare att titta på dina åtaganden, vilket innebär att det är en offentlig filial. Att skriva om sin historia gör det omöjligt för Git och dina lagkamrater att spåra eventuella uppföljningsåtaganden som läggs till funktionen.
eventuella ändringar från andra utvecklare måste införlivas medgit merge
istället förgit rebase
.,
av den anledningen är det vanligtvis en bra idé att städa upp din kod med en interaktiv rebase innan du skickar in din pull-förfrågan.
integrera en godkänd funktion
Efter att en funktion har godkänts av ditt team, har du möjlighet att rebasera funktionen på spetsen avmaster
filialen innan du användergit merge
för att integrera funktionen i huvudkodsbasen.,
det här är en liknande situation som att införliva uppströmsändringar i en funktionsgren, men eftersom du inte får skriva om åtaganden i master
– grenen måste du så småningom använda git merge
för att integrera funktionen. Men genom att utföra en rebase före sammanfogningen är du säker på att sammanfogningen kommer att vidarebefordras snabbt, vilket resulterar i en perfekt linjär historia. Detta ger dig också chansen att squash eventuella uppföljningsåtaganden läggs under en pull begäran.,
om du inte är helt bekväm med git rebase
kan du alltid utföra rebasen i en tillfällig gren. På så sätt, om du av misstag förstöra din funktion historia, kan du kolla in den ursprungliga grenen och försöka igen. Till exempel:
git checkout feature git checkout -b temporary-branch git rebase -i master # git checkout master git merge temporary-branch
sammanfattning
och det är allt du verkligen behöver veta för att börja rebasera dina grenar., Om du föredrar en ren, linjär historia utan onödiga sammanslagningar, bör du nå git rebase
I stället för git merge
när du integrerar ändringar från en annan gren.
å andra sidan kan du hålla fast vid git merge
om du vill bevara projektets fullständiga historia och undvika risken för att allmänheten åtar sig att skriva om. Båda alternativen är helt giltiga, men åtminstone nu har du möjlighet att utnyttja fördelarna med git rebase
.
Lämna ett svar