I den grunnleggende Git-arbeidsflyten utvikler du en ny funksjon i en dedikert faggren, og legger den sammen igjen i en produksjonsgren når den er ferdig. Dette gjør git fusjon
et integrert verktøy for å kombinere grener. Det er imidlertid ikke den eneste Git tilbyr.
Som et alternativ til ovenstående scenario kan du kombinere grener med git rebase
kommando. I stedet for å knytte grenene sammen med et fusjonssammenheng, flytter gjenopprettelse hele funksjonen grenen til spissen av herre
som vist under.
Dette tjener samme formål som git fusjon
, integrering forplikter seg fra forskjellige grener. Men det er to grunner til at vi kanskje vil velge en rebase over en fusjon:
I denne opplæringen vil vi undersøke disse to vanlige tilfellene av git rebase
. Dessverre fordelene med git rebase
kom på en avgang. Når det brukes feil, kan det være en av de farligste operasjonene du kan utføre i et Git-arkiv. Så, vi vil også ta et forsiktig utseende på farene ved gjenoppretting.
Denne opplæringen tar utgangspunkt i at du er kjent med de grunnleggende Git-kommandoene og samarbeidsprosessene. Du bør være komfortabel oppføring og begå øyeblikksbilder, utvikle funksjoner i isolerte grener, slå sammen grener sammen og skyve / trekke grener til / fra eksterne lagre.
Den første brukssaken vi vil utforske innebærer en divergerende prosjekthistorikk. Tenk på et lager der produksjonsgrenen din har flyttet fremover mens du utviklet en funksjon:
Å rebase trekk
gren på herre
gren, ville du kjøre følgende kommandoer:
git checkout funksjon git rebase master
Dette transplanterer trekk
gren fra sin nåværende beliggenhet til toppen av herre
gren:
Det er to scenarier hvor du vil gjøre dette. Først, hvis funksjonen var avhengig av det nye begår seg i herre
, det ville nå få tilgang til dem. For det andre, hvis funksjonen var fullført, ville den nå bli konfigurert for å gå videre sammen herre
. I begge tilfeller resulterer gjenoppretting i en lineær historie, mens git fusjon
ville resultere i unødvendige sammenslåingsforpliktelser.
For eksempel, vurder hva som ville skje hvis du integrerte oppstrømmen forplikter seg til en fusjon i stedet for en tilbakekomst:
git checkout funksjonen Git Merge Master
Dette ville ha gitt oss en ekstra fletteforpliktelse i trekk
gren. I tillegg vil dette skje hver gang du ønsker å innlemme oppstrøms forpliktelser i funksjonen din. Til slutt vil prosjekthistorikken din være full av meningsløse sammenføyningsforpliktelser.
Den samme fordelen kan sees ved sammenslåing i den andre retningen. Uten en rebase, integrering av ferdig trekk
grenen inn i herre
krever en fletteforpliktelse. Selv om dette faktisk er en meningsfylt sammenslåing (i den forstand at den representerer en fullført funksjon), er den resulterende historien full av gafler:
Når du reagerer før du slår sammen, kan Git spole fremover herre
til spissen av trekk
. Du finner en lineær historie om hvordan prosjektet ditt har utviklet seg i git logg
output-den forplikter seg i trekk
er pent gruppert sammen på toppen av forpliktelsene i herre
. Dette er ikke nødvendigvis tilfelle når grener er bundet sammen med et sammenslåingsforpliktelse.
Når du kjører git rebase
, Git tar hver forpliktelse i grenen og beveger dem, en for en, på den nye basen. Hvis noen av disse forbinder, endrer samme linje (r) av kode som oppstrømsforbindelsen, vil det føre til konflikt.
De git fusjon
Kommandoen lar deg løse alle grenens konflikter ved slutten av sammenslåingen, noe som er et av de primære formålene med en sammenslåing. Det virker imidlertid litt annerledes når du reagerer. Konflikter er løst på grunnlag av hverandre. Så hvis git rebase
finner konflikt, vil det stoppe tilbakekallingsprosedyren og vise en advarselsmelding:
Automatisk sammensmelting readme.txt CONFLICT (innhold): Slå sammen konflikt i readme.txt Kunne ikke slå sammen i endringene ... Når du har løst dette problemet, kjør "git rebase - continue". Hvis du foretrekker å hoppe over denne oppdateringen, kjør du "git rebase - skip" i stedet. For å sjekke ut den opprinnelige grenen og stoppe gjenoppretting, kjør "git rebase --abort".
Visuelt, dette er hva prosjektloggen din ser ut når git rebase
møter en konflikt:
Konfliktene kan inspiseres ved å løpe git status
. Utgangen ser veldig ut som en flettekonflikt:
Unmerged paths: (bruk "git reset HEAD... "til unstage) (bruk" git add ... "for å markere oppløsning) begge endret: readme.txt ingen endringer lagt til for å begå (bruk" git add "og / eller" git commit -a ")
For å løse konflikten, åpne den konfliktfile filen (readme.txt i eksempelet ovenfor), finn de berørte linjene, og rediger dem manuelt til ønsket resultat. Deretter forteller Git at konflikten er løst ved å lagre filen:
git legg til readme.txt
Vær oppmerksom på at dette er nøyaktig samme måte du markerer en git fusjon
konflikt som løst. Men husk at du er midt i en rebase-du vil ikke glemme resten av begjærene som må flyttes. Det siste trinnet er å fortelle Git å fullføre gjenoppretting med --Fortsette
alternativ:
git rebase - fortsette
Dette vil flytte resten av forpliktelsene, en for en, og hvis noen andre konflikter oppstår, må du gjenta denne prosessen på nytt..
Hvis du ikke vil løse konflikten, kan du velge enten --hoppe
eller --avbryte
flagg. Sistnevnte er spesielt nyttig hvis du ikke har noen anelse om hva som skjer, og vil bare komme tilbake til sikkerhet.
# Ignorer forpligningen som forårsaket konflikten git rebase - skip # Abort hele rebasen og gå tilbake til tegnebrettet git rebase --abort
Så langt har vi bare brukt git rebase
å flytte grener, men det er mye kraftigere enn det. Ved å passere -Jeg
flagg, kan du starte en interaktiv, nybegynnende økt. Interaktiv gjenoppretting lar deg definere nøyaktig hvordan hver commit blir flyttet til den nye basen. Dette gir deg muligheten til å rydde opp en funksjonens historie før du deler den med andre utviklere.
For eksempel, la oss si at du er ferdig med å jobbe på din trekk
gren og du er klar til å integrere den i herre
. For å starte en interaktiv gjentatt økt, kjør følgende kommando:
git checkout funksjon git rebase -i master
Dette åpner en redaktør som inneholder alle forpliktelsene i trekk
som er i ferd med å bli flyttet:
velg 5c43c2b [Beskrivelse for eldste commit] velg b8f3240 [Beskrivelse for 2. eldste commit] velg c069f4a [Beskrivelse for siste commit]
Denne oppføringen definerer hva trekk
gren kommer til å ligne etter rebasen. Hver linje representerer en commit og plukke
kommandoen før hver forpliktelse har definert hva som skal skje i løpet av tilbakemeldingen. Legg merke til at begjærene er oppført fra eldste til siste. Ved å endre denne oppføringen får du full kontroll over prosjekthistorikken din.
Hvis du vil endre rekkefølgen på forpliktelsene, kan du bare ordne linjene på nytt. Hvis du vil endre en kommandos melding, bruker du omformulere
kommando. Hvis du vil kombinere to forpliktelser, endrer du plukke
kommandoen til squash
. Dette vil rulle alle endringene i den forpliktelsen til den over den. For eksempel, hvis du squashed den andre begå i ovennevnte oppføring, vil trekk
gren vil se ut som følgende etter lagring og lukking av redaktøren:
De redigere
kommandoen er spesielt kraftig. Når den når det angitte forbudet, vil Git sette pause på tilbakekallingsprosedyren, omtrent som når den møter en konflikt. Dette gir deg muligheten til å endre innholdet i forplikten med git commit --amend
eller til og med legge til flere forpliktelser med standarden git add
/git commit
kommandoer. Eventuelle nye forpliktelser du legger til, vil være en del av den nye grenen.
Interaktiv gjenoppretting kan ha en dyp innvirkning på utviklingsarbeidet. I stedet for å bekymre seg for å bryte opp endringene i innkapslede forpliktelser, kan du fokusere på å skrive koden din. Hvis du endte opp med å begå hva som skulle være en enkelt endring i fire separate stillbilder, er det ikke et problem med omskrivning av historie med git rebase -i
og squash dem alle til en meningsfull begå.
Nå som du har forståelse for git rebase
, vi kan snakke om når vi ikke skal bruke den. Internt tilbakeleverer faktisk ikke flytte forplikter seg til en ny avdeling. I stedet skaper det splitter nye forpliktelser som inneholder de ønskede endringene. Med dette er tankene, er rebasing bedre visualisert som følgende:
Etter tilbakemeldingen går den inn i trekk
vil ha forskjellige forpliktelser. Dette betyr at vi ikke bare flyttet en gren - vi har bokstavelig talt omskrevet vår prosjekthistorie. Dette er en svært viktig bivirkning av git rebase
.
Når du jobber alene på et prosjekt, er omskrivning av historie ikke en stor sak. Men så snart du begynner å jobbe i et samarbeidsmiljø, kan det bli veldig farlig. Hvis du skriver om, forplikter andre utviklere å bruke (for eksempel forplikter seg på herre
gren), det vil se ut som om de begår forsvunnet neste gang de prøver å trekke inn arbeidet ditt. Dette resulterer i et forvirrende scenario som er vanskelig å gjenopprette fra.
Med dette er tankene, bør du aldri glemme forpliktelser som har blitt presset til et offentligt arkiv med mindre du er positiv at ingen har basert sitt arbeid av dem.
Denne opplæringen introduserte de to vanligste brukssakene til git rebase
. Vi snakket mye om å flytte grener rundt, men husk at gjenoppretting egentlig handler om å kontrollere prosjekthistorikken. Kraften til omskrivning forplikter seg etter at friheten gjør at du fokuserer på utviklingsoppgaver i stedet for å bryte ned arbeidet ditt i isolerte stillbilder.
Legg merke til at gjenoppretting er et helt valgfritt tillegg til Git-verktøykassen. Du kan fortsatt gjøre alt du trenger med vanlig gammel git fusjon
kommandoer. Faktisk er dette sikrere, da det unngår muligheten for å omskrive offentlig historie. Men hvis du forstår risikoen, git rebase
kan være en mye renere måte å integrere grener i forhold til fusjonerende forpliktelser.