git rebase – kommandoen har et rykte for å være magisk Git voodoo at nybegynnere bør holde deg unna, men det kan faktisk gjøre livet mye lettere for en utvikling team når det brukes med forsiktighet. I denne artikkelen vil vi sammenligne git rebase med tilhørende git merge kommando og identifisere alle potensielle muligheter for å innlemme rebasing inn i de typiske Git arbeidsflyt.,

Konseptuell Oversikt

Den første tingen å forstå om git rebase er at det løser det samme problemet som git merge. Begge disse kommandoene er utformet for å integrere forandringer fra en gren til en annen gren—de bare gjør det på svært ulike måter.

Tenk hva som skjer når du begynner å arbeide på en ny funksjon i en egen gren, og et annet medlem av teamet, oppdaterer master gren med nye forplikter. Dette resulterer i en kløft historie, som bør være kjent for alle som har brukt Git som et samarbeid verktøyet.,

Nå, la oss si at den nye begår i master er relevante i forhold til den funksjonen du jobber på. Å innarbeide nye begår inn din feature gren, har du to alternativer: sammenslåing eller rebasing.,

Merge Alternativ

Den enkleste alternativet er å slå sammen master branch i branch har ved hjelp av noe som følgende:

git checkout feature git merge master

Eller, du kan kondensere dette til en one-liner:

 git merge feature master

Dette skaper en ny «merge har begått» i feature gren som knytter sammen historier om begge grener, og gir deg en gren struktur som ser ut som dette:

Sammenslåing er fint fordi det er en ikke-destruktiv drift. Den eksisterende filialer er ikke endret på noen måte., Dette unngår alle de potensielle fallgruvene av rebasing (diskutert nedenfor).

På den annen side, dette betyr også at feature grenen vil ha en ekstra flette forplikte seg hver gang du trenger å innlemme oppstrøms endringer. Hvis master er veldig aktiv, dette kan forurense din funksjonen gren historie som er ganske mye. Mens det er mulig å redusere problemet med avansert git log valg, det kan gjøre det vanskelig for andre utviklere å forstå historien av prosjektet.,

De Rebase Alternativ

Som et alternativ til sammenslåing, kan du rebase feature gren på master gren ved hjelp av følgende kommandoer:

git checkout feature git rebase master

Dette flytter hele feature gren til å begynne på tuppen av master gren, effektivt å innlemme alle de nye begår i master. Men, i stedet for å bruke en flette begå, rebasing re-skriver prosjekt historie ved å skape helt nye begår for hver innlegging i den opprinnelige gren.,

Den største fordelen av rebasing er at du får en mye renere prosjektet historie. For det første, det eliminerer unødvendige fusjonere begår kreves av git merge. Andre, som du kan se i diagrammet ovenfor, rebasing også resulterer i en perfekt lineær prosjektet historie—du kan følge med på tuppen av feature helt til begynnelsen av prosjektet uten noen gafler. Dette gjør det enklere å navigere i prosjektet med kommandoer som git log, git bisect, og gitk.,

Men, det er to trade-offs for denne uberørte begå historie: sikkerhet og sporbarhet. Hvis du ikke følger den Gylne Regelen av Rebasing, re-skriving prosjektet historie kan være potensielt katastrofale for samarbeid din arbeidsflyt. Og, mindre viktig, rebasing mister den sammenheng gitt ved en sammenslåing commit—du kan ikke se når oppstrøms endringer ble innlemmet i funksjon.

Interaktiv Rebasing

Interaktiv rebasing gir deg muligheten til å endre begår når de er flyttet til den nye grenen., Dette er enda kraftigere enn en automatisert rebase, siden det gir full kontroll over grenen er begått historie. Dette er vanligvis brukt til å rydde opp i en rotete historie før sammenslåing en funksjon gren i master.,

for Å begynne en interaktiv rebasing økten, passere i alternativ til git rebase kommando:

git checkout feature git rebase -i master

Dette vil åpne en tekstredigerer for å vise alle av de begår som er i ferd med å bli flyttet:

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

Denne oppføringen angir nøyaktig hva grenen vil se ut etter rebase er utført. Ved å endre pick kommando og/eller re-bestilling av oppføringene, kan du gjøre gren historie ser ut som hva du vil., For eksempel, hvis den 2. forplikte løser et lite problem i 1. begå, kan du kombinere dem i en enkelt forplikte med fixup kommando:

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

Når du lagre og lukk filen, Git vil utføre rebase i henhold til dine instruksjoner, noe som resulterer i prosjektet historie som ser ut som følgende:

Eliminere ubetydelig begår som dette gjør at funksjonen er historien mye lettere å forstå. Dette er noe som git merge rett og slett ikke kan gjøre.,

Den Gylne Regelen av Rebasing

Når du forstår hva rebasing er, er det viktigste å lære på er når man ikke skal gjøre det. Den gylne regelen av git rebase er å aldri bruke det på offentlig grener.

For eksempel, tenk på hva som ville skje hvis du rebased master til feature gren:

rebase flytter alle begår i master på tuppen av feature. Problemet er at dette bare skjedde i depotet., Alle de andre utviklerne jobber fortsatt med det opprinnelige master. Siden rebasing resultater i ny begår, Git vil tro at master gren historie har skilte seg fra alle andres.

Den eneste måten å synkronisere de to master grener, er å flette dem sammen igjen, noe som resulterer i en ekstra flette begå, og to sett av begår som inneholder de samme endringene (den opprinnelige, og de fra din rebased gren). Unødvendig å si, dette er en veldig forvirrende situasjon.,

Så, før du kjører git rebase, alltid spørre deg selv, «Er det noen andre som ser på dette gren?»Hvis svaret er ja, ta hendene bort fra tastaturet og begynne å tenke på en ikke-destruktiv måte å gjøre endringer (f.eks., git revert – kommandoen). Ellers, du er trygg til å skrive om historien så mye som du liker.

Force-Presser

Hvis du prøver å presse rebased master gren tilbake til en ekstern depotet, Git vil hindre deg fra å gjøre det fordi det er i strid med eksterne master gren., Men, kan du tvinge presse til å gå gjennom ved å sende --force flagg, for eksempel slik:

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

Dette overskriver den eksterne master grenen for å matche rebased en fra depotet, og gjør ting veldig forvirrende for resten av teamet. Så, være svært forsiktig med å bruke denne kommandoen bare når du vet nøyaktig hva du gjør.

En av de eneste gangene du bør være kraft-presser er når du har utført en lokal opprydding etter at du har presset en egen funksjon gren til en ekstern depotet (f.eks., til backup-formål)., Dette er som å si, «Oops, jeg hadde egentlig ikke ønsker å presse den opprinnelige versjonen av funksjonen gren. Ta det aktuelle stedet.»Igjen er det viktig at ingen er i arbeid ut av forplikter seg fra den opprinnelige versjonen av funksjonen gren.

Arbeidsflyt Gjennomgang

Rebasing kan bli tatt inn i din eksisterende Git arbeidsflyt så mye eller så lite som laget ditt er komfortabel med. I denne delen vil vi ta en titt på fordelene som rebasing kan tilby på ulike stadier av en funksjon utvikling.,

Det første trinnet i enhver arbeidsflyt som utnytter git rebase er å opprette en egen gren for hver funksjon. Dette gir deg nødvendig gren struktur for å trygt bruke rebasing:

Lokale Opprydding

En av de beste måtene å innlemme rebasing inn i din arbeidsflyt er å rydde opp i lokale, in-progress funksjoner. Med jevne mellomrom utføre en interaktiv rebase, kan du være sikker på at hver commit i din funksjonen er fokusert og meningsfylt., Dette lar deg skrive koden din uten å bekymre deg om å bryte den opp i isolerte forplikter—kan du fikse det opp i ettertid.

Når du ringer git rebase du har to alternativer for den nye base: funksjonen er forelder gren (f.eks., master), eller en tidligere begått i funksjon. Vi så et eksempel på det første alternativet i den Interaktive Rebasing delen. Det siste alternativet er fint når du bare trenger å fikse opp de siste par forplikter. For eksempel, følgende kommando begynner en interaktiv rebase av bare de siste 3 forplikter.,

git checkout feature git rebase -i HEAD~3

Ved å angi HEAD~3 som ny base, du er faktisk ikke flytte gren—du er bare interaktivt re-skriving 3 begår som følger det. Merk at dette ikke vil innlemme oppstrøms endringer i feature gren.

Hvis du ønsker å re-skriver hele funksjon ved hjelp av denne metoden, git merge-base – kommandoen kan være nyttig for å finne den opprinnelige base av feature gren., Følgende returnerer begå ID-en for den opprinnelige base, som du deretter kan passere til git rebase:

git merge-base feature master

Dette bruk av interaktive rebasing er en flott måte å introdusere git rebase inn i din arbeidsflyt, som det bare påvirker lokale avdelinger. Det eneste andre utviklere vil se er det ferdige produktet, som skal være en ren, lett-å-følge-funksjonen gren historie.

Men igjen, dette fungerer bare for privat-funksjonen grener., Hvis du samarbeider med andre utviklere via den samme funksjonen gren, at grenen er offentlig, og du har ikke lov til å skrive sin historie.

Det er ingen git merge alternativ for å rydde opp lokale begår med en interaktiv rebase.

Innlemme Oppstrøms Endringer I en Funksjon

I den Konseptuelle delen Oversikt over, vi så hvordan en funksjon branch kan innlemme oppstrøms endringer fra master ved hjelp av enten git merge eller git rebase., Sammenslåing er et trygt alternativ som bevarer hele historien av depotet, mens rebasing skaper en lineær historie ved å flytte funksjonen gren på tuppen av master.

Dette bruk av git rebase er lik en lokal opprydding (og kan utføres samtidig), men i den prosessen det har de oppstrøms begår fra master.

husk at det er helt lovlig å rebase på en ekstern grenen i stedet for master., Dette kan skje når samarbeide om den samme funksjonen med en annen utvikler og du trenger å innlemme sine forandringer til depotet.,

For eksempel, hvis du og en annen utvikler heter John lagt forplikter seg til å feature branch, i depotet kan se ut som følgende etter å hente den eksterne feature gren fra John ‘ s depotet:

Du kan løse dette gaffel på nøyaktig samme måte som du integrere oppstrøms endringer fra master: enten å fusjonere din lokale feature med john/feature, eller rebase din lokale feature på tuppen av john/feature.,

Merk at dette rebase ikke bryter den Gylne Regelen av Rebasing fordi bare en lokal feature forplikter blir flyttet på—alt før det er urørt. Dette er som å si, «legge til mine endringer til hva han har gjort det allerede.»I de fleste tilfeller, dette er mer intuitivt enn synkronisering med ekstern grenen via en flette begå.

standard git pull kommando utfører en utskriftsfletting, men du kan tvinge den til å integrere den eksterne gren med en rebase ved å føre det --rebase alternativ.,

Gjennomgå en Funksjon Med et Trekk Forespørsel

Hvis du bruker trekke forespørsler som en del av koden din gjennomgangen, du må unngå å bruke git rebase etter å skape trekk forespørsel. Så snart du gjøre trekk forespørsel, andre utviklere vil være å se på forplikter, noe som betyr at det er en offentlig gren. Re-skrive sin historie vil gjøre det umulig for Git og lagkameratene for å spore eventuell oppfølging begår lagt til funksjonen.

Eventuelle endringer fra andre utviklere trenger å bli tatt med git merge i stedet for git rebase.,

på grunn av dette, er det vanligvis en god idé å rydde opp i koden din med en interaktiv rebase før du sender inn din trekk forespørsel.

Integrere en Godkjent Funksjonen

Etter at en funksjon har blitt godkjent av laget ditt, du har muligheten til rebasing funksjonen på tuppen av master gren før du bruker git merge for å integrere funksjonen til de viktigste koden.,

Dette er en lignende situasjon til å innlemme oppstrøms endringer i en funksjon gren, men siden du ikke lov til å skrive om begår i master gren, har du til slutt bruke git merge for å integrere funksjonen. Imidlertid, ved å utføre en rebase før flettingen, du er trygg på at flettingen vil være rask-forwarded, noe som resulterer i en perfekt lineær historie. Dette gir deg også muligheten til å ta knekken på eventuell oppfølging begår lagt under et trekk forespørsel.,

Hvis du ikke er helt komfortabel med git rebase, kan du alltid utføre rebase i en midlertidig gren. På den måten, hvis du ved et uhell rote opp din funksjonen er historie, kan du sjekke ut den opprinnelige gren, og prøv på nytt. For eksempel:

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

Oppsummering

Og det er egentlig alt du trenger å vite for å starte rebasing dine grener., Hvis du foretrekker en ren, lineær historie fri for unødvendige slå sammen forplikter, bør du nå for git rebase i stedet for git merge ved å integrere endringer fra en annen gren.

På den annen side, hvis du ønsker å bevare komplett historikk av prosjektet for å unngå risiko for re-skriving offentlige forplikter, kan du feste med git merge. Enten alternativet er helt gyldig, men minst nå har du muligheten til å utnytte fordelene av git rebase.