Omskriving History med Git Rebase

Rewriting History med Git Rebase
57
Del
Del
Del

Dette Cyber ​​mandag Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.

I den grunnleggende Git arbeidsflyten, utvikler du en ny funksjon i et eget tema gren, deretter flette den tilbake i en produksjon gren når den er ferdig. Dette gjør git flette et integrert verktøy for å kombinere grener. Men det er ikke den eneste som Git tilbyr.
Kombinere grener ved å flette dem sammen

Som et alternativ til ovennevnte scenario, kan du kombinere grenene med git rebase kommandoen. I stedet for å binde grenene sammen med et flette begå, beveger rebasing hele funksjonen gren til tuppen av mesteren, som vist nedenfor.
Kombinere grener med git rebase

Dette tjener samme formål som git merge, integrere inger fra ulike grener. Men det er to grunner til at vi kanskje ønsker å velge en rebase over en flette:

Det resulterer i en lineær prosjekt historie

Det gir oss muligheten til å rydde opp lokalt. begår.

I denne opplæringen, vil vi utforske disse to vanlige bruksmåter av git rebase. Dessverre, fordelene med git rebase kommet på et trade-off. Når den brukes på feil måte, kan det være en av de farligste operasjoner du kan utføre i et Git repository. Så vil vi også ta en nøye titt på farene ved rebasing.

Forutsetninger

Denne opplæringen forutsetter at du er kjent med de grunnleggende Git-kommandoer og samarbeidsarbeidsflyter. Du bør være komfortabel iscenesettelse og begår snapshots, utviklingsfunksjonene i isolerte grener, sammenslåing grenene sammen, og skyve /trekke grener til /fra eksterne repositories.

1. Rebasing for en lineær historie

Den første bruken tilfelle vi vil utforske innebærer en avvikende prosjekt historie. Vurdere et depot der produksjonen grenen har beveget seg fremover mens du var å utvikle en egenskap:

For å rebase funksjonen gren på master gren, ville du kjøre følgende kommandoer:
git checkout featuregit rebase mester

Dette transplantasjoner funksjonen gren fra gjeldende plassering til spissen av hovedgren:

Det er to scenarier der du ønsker å gjøre dette. Først, hvis funksjonen støttet seg på de nye innlegginger i master, det ville nå ha tilgang til dem. For det andre, hvis funksjonen var ferdig, det vil nå bli satt opp for en hurtig fremover flette inn mester. I begge tilfeller rebasing resultater i en lineær historie, mens git merge ville resultere i unødvendig merge forplikter

For eksempel vurdere hva som ville skje hvis du integrert oppstrøms begår med en flette i stedet for et rebase:.
git checkout featuregit fusjonere mester

Dette ville ha gitt oss en ekstra merge begå i funksjonen grenen. Hva mer, ville dette skje hver gang du ønsket å innlemme oppstrøms begår inn i funksjonen. Etter hvert vil prosjektet historie bli strødd med meningsløs flettingen forplikter.
Integrering oppstrøms begår med et flette

Den samme fordelen kan sees ved sammenslåing i den andre retningen. Uten rebase, integrere det ferdige funksjonen gren inn mester krever et flette begå. Selv om dette er faktisk et menings merge forplikte (i den forstand at det representerer en ferdig funksjon), er den resulterende historie full av gafler:
Integrering av en ferdig funksjon med et flette

Når du rebase før sammenslåing, er Git stand for å spole fremover mester til tuppen av funksjonen. Du vil finne en lineær historie om hvordan prosjektet har kommet i git log utgangs-de inger i funksjonen er pent gruppert sammen på toppen av innlegginger i herre. Dette er ikke nødvendigvis tilfelle når grenene er knyttet sammen med et flette begå.
Rebasing før sammenslåing
Løse konflikter

Når du kjører git rebase tar Git hver innlegging i grenen og flytter dem, en etter en, på den nye basen. Hvis noen av disse begår endre den samme linjen (e) med kode som oppstrøms forplikter, vil det resultere i en konflikt.

git merge-kommandoen kan du løse alle filialens konflikter på slutten av flettingen , som er en av de viktigste formålene med et flette begå. Men det fungerer litt annerledes når du rebasing. Konflikter løses på en per-commit basis. Så hvis git rebase finner en konflikt, vil det stoppe rebase prosedyre og vise en advarsel:
Auto-sammenslåing readme.txtCONFLICT (innhold): Flett konflikten i readme.txtFailed å flette inn endringene ..... Når du har løst dette problemet ved å kjøre "git rebase --continue" .Hvis du foretrekker å hoppe over denne oppdateringen, kjøre "git rebase --skip" instead.To sjekke ut den opprinnelige grenen og stoppe rebasing, kjøre "git rebase - abortere "

Visuelt er dette hva prosjektet historie ser ut når git rebase møter en konflikt.

Konfliktene kan inspiseres ved å kjøre git status. Utgangen ser veldig lik en sammenslåing konflikt:
Unmerged stier: (bruk "reset git HEAD < fil > ..." for å unstage) (bruk "git legge < fil > ..." for å markere oppløsning) både endret: readme.txtno endringer legges forplikte (bruk "git legge til" og /eller "git commit a")

For å løse konflikten, åpne opp fil i konflikt (readme.txt i eksempelet ovenfor), finner de berørte linjer, og manuelt redigere dem til det ønskede resultat. Deretter forteller Git at konflikten er løst ved å sette opp filen:
git legge readme.txt

Merk at dette er nøyaktig samme måte som du merke en git fusjonere konflikten løst. Men husk at du er i midten av en rebase-du ikke ønsker å glemme resten av innlegginger som må flyttes. Det siste trinnet er å fortelle Git å avslutte rebasing med --continue alternativ:
git rebase --continue

Dette vil flytte resten av innlegginger, en etter en, og hvis noen andre konflikter oppstår, du må gjenta denne prosessen på nytt.

Hvis du ikke ønsker å løse konflikten, kan du velge enten --skip eller --abort flagg. Sistnevnte er spesielt nyttig hvis du har ingen anelse om hva som skjer og bare ønsker å komme tilbake i sikkerhet.
# Ignorer begå som forårsaket conflictgit rebase --skip # Abort hele rebase og gå tilbake til tegne boardgit rebase --abort
2. Rebasing å rydde opp Local begår

Så langt har vi bare brukt git rebase å flytte grener, men det er mye kraftigere enn det. Ved passering av flagget, kan du begynne en interaktiv rebasing økt. Interaktiv rebasing lar deg definere nøyaktig hvordan hver innlegging vil bli flyttet til den nye basen. Dette gir deg muligheten til å rydde opp en funksjon historie før du deler den med andre utviklere.

For eksempel, la oss si at du er ferdig med å jobbe på funksjonen gren og du er klar til å integrere den i herre. Til å begynne en interaktiv rebasing økt, kjører du følgende kommando:
git checkout featuregit rebase -i mester

Dette vil åpne en redaktør som inneholder alle innlegginger i funksjonen som er i ferd med å bli flyttet:
plukke 5c43c2b [Description for eldste begå] plukke b8f3240 [Beskrivelse for andre eldste begå] plukke c069f4a [Beskrivelse for siste begå]

Denne listen definerer hva funksjonen grenen kommer til å se ut etter rebase. Hver linje representerer en innlegging og pick-kommandoen før hver forplikte hash definerer hva som kommer til å skje med det i løpet av rebase. Merk at inger er oppført fra eldste til nyeste. Ved å endre denne oppføringen, får du full kontroll over ditt prosjekt historie.

Hvis du vil endre rekkefølgen på inger, rett og slett endre rekkefølgen på linjene. Hvis du ønsker å endre en forplikte budskap, bruker reword kommandoen. Hvis du ønsker å kombinere to inger, endre pick-kommandoen til squash. Dette vil rulle alle endringene i at bryte inn i den ene over den. For eksempel, hvis du klemt den andre begår i ovennevnte liste, ville funksjonen gren se slik ut etter lagring og lukking redaktør:
squashing den andre begår med en interaktiv rebase

redigere kommandoen er spesielt kraftig. Når den når den angitte innlegging, vil Git pause rebase prosedyren, omtrent som når det oppstår en konflikt. Dette gir deg muligheten til å endre innholdet i forplikte med git commit --amend eller legge til flere inger med standard git legge /git commit kommandoer. Eventuelle nye inger du legger til, vil være en del av den nye grenen.

Interaktiv rebasing kan ha stor innvirkning på utviklingen arbeidsflyt. I stedet for å bekymre deg for å bryte opp endringene i innkapslede inger, kan du fokusere på å skrive koden din. Hvis du endte opp med å binde hva som bør være en enkel endring i fire separate snapshots, så det er ikke et problem-omskrive historien med git rebase -i og squash dem alle i en meningsfull begå.

3. Farene ved Rebasing

Nå som du har en forståelse av git rebase, kan vi snakke om når man ikke skal bruke den. Internt betyr rebasing faktisk ikke flytte forplikter seg til en ny gren. I stedet, det skaper helt nye inger som inneholder de ønskede endringer. Med dette er tankene, er rebasing bedre visualisert som følgende:

Etter rebase, de inger i funksjonen vil ha forskjellige hashes. Dette betyr at vi ikke bare flytte en gren-vi har bokstavelig talt omskrevet vårt prosjekt historie. Dette er en svært viktig bivirkning av git rebase.

Når du arbeider alene på et prosjekt, omskriving historie er ikke en stor avtale. Men så snart du begynner å arbeide i et samarbeidsmiljø, kan det bli veldig farlig. Hvis du omskrive begår at andre utviklere bruker (for eksempel begår på master gren), vil det se ut som om disse inger forsvunnet neste gang de prøver å trekke i arbeidet. Dette resulterer i en forvirrende situasjon som er vanskelig å komme seg fra.

Med dette er tankene, bør du aldri rebase inger som har blitt presset til et offentlig register med mindre du er positivt at ingen har basert sitt arbeid ut av dem .

Konklusjon

Denne opplæringen introduserte de to mest vanlige bruksmåter av git rebase. Vi snakket mye om å flytte greiner rundt, men husk at rebasing egentlig dreier seg om å styre prosjektet historie. Makt til å omskrive inger i ettertid frigjør deg til å fokusere på utviklingsoppgaver i stedet for å bryte ned arbeidet i isolerte snapshots.

Merk at rebasing er en helt valgfritt tillegg til Git verktøykasse. Du kan fortsatt gjøre alt du trenger å med ren gamle git fusjonere kommandoer. Faktisk er dette sikrere fordi man unngår muligheten for å omskrive offentlig historie. Men hvis du forstår risikoen, kan git rebase være en mye renere måte å integrere grener i forhold til sammenslåing inger.



Previous:
Next Page: