Grener multipliserer den grunnleggende funksjonaliteten som tilbys av forpliktelser ved at brukerne kan gaffelere sin historie. Opprette en ny avdeling er knyttet til å be om et nytt utviklingsmiljø, komplett med en isolert arbeidskatalog, staging-område og prosjekthistorie.
Dette gir deg samme sjelefred som å begå en "sikker" kopi av prosjektet ditt, men du har nå den ekstra kapasiteten til å jobbe på flere versjoner på samme tid. Grener aktiverer a ikke-lineær arbeidsflyt-evnen til å utvikle ikke-relaterte funksjoner parallelt. Som vi vil oppdage senere, er en ikke-lineær arbeidsflyt en viktig forløper til den distribuerte naturen til Gits samarbeidsmodell.
I motsetning til SVN eller CVS, er Gits grensesnittimplementasjon utrolig effektiv. SVN muliggjør grener ved å kopiere hele prosjektet til en ny mappe, akkurat som du ville gjøre uten revisjonskontrollprogramvare. Dette gjør fusjoner klumpete, feilaktig og sakte. I kontrast er Git grener rett og slett en pointer til en forpliktelse. Siden de jobber på commit-nivået i stedet for direkte på filnivået, gjør Git-grener det mye lettere å slå sammen divergerende historier. Dette har en dramatisk innvirkning på forgreningsarbeid.
Git skiller grenfunksjonalitet i noen få forskjellige kommandoer. De git grenen
Kommandoen brukes til å opprette, lage eller slette grener.
Først og fremst må du se dine eksisterende grener:
git grenen
Dette vil utdata alle dine nåværende grener, sammen med en stjerne ved siden av den som er "sjekket ut" (mer om det senere):
* master noen funksjon hurtig bug-fix
De herre
grenen er Gits standard grenen, som er opprettet med den første forplikten i et hvilket som helst arkiv. Mange utviklere bruker denne grenen som "hoved" historie av prosjektet - en permanent gren som inneholder alle de store endringene det går gjennom.
Du kan opprette en ny filial ved å sende grennavnet til det samme git grenen
kommando:
git grenen
Dette skaper en peker til gjeldende HODE
, men gjør det ikke bytt til den nye grenen (du trenger git kassen
for det). Umiddelbart etter at du har bedt om en ny filial, vil ditt arkiv se ut som følgende.
Din nåværende gren (herre
) og den nye grenen (noen-feature
) begge refererer til samme forpliktelse, men noe nytt forplikter deg, vil være eksklusivt for den nåværende grenen. Igjen, dette lar deg arbeide på ikke-relaterte funksjoner parallelt, samtidig som du opprettholder fornuftige historier. For eksempel, hvis din nåværende grense var noen-feature
, Historien din vil se ut som følgende etter å ha begått et øyeblikksbilde.
noen-feature
gren Den nye HODE
(betegnet av det fremhevede forbudet) eksisterer bare i noen-feature
gren. Det kommer ikke opp i loggutgangen til herre
, og endringene vises ikke i arbeidskatalogen etter at du har sjekket ut herre
.
Du kan faktisk se den nye grenen i den interne databasen ved å åpne filen .git / refs / hoder /
. Filen inneholder ID for referert commit, og det er den eneste definisjonen av en Git grenen. Dette er grunnen til at grener er så lette og enkle å håndtere.
Endelig kan du slette grener via -d
flagg:
git grenen -d
Men Gits engasjement for å aldri miste arbeidet forhindrer det i å fjerne grener med ubemerkede forpliktelser. For å tvinge slettingen, bruk -D
flagg i stedet:
git grenen -D
Unmerged endringer vil gå tapt, så vær veldig forsiktig med denne kommandoen.
Selvfølgelig er å lage grener ubrukelig uten muligheten til å bytte mellom dem. Git kaller dette "sjekke ut" en gren:
git kassen
Etter at du har sjekket ut den angitte grenen, er arbeidskatalogen oppdatert for å matche den angitte grensesektoren. i tillegg HODE
er oppdatert for å peke på den nye grenen, og alle nye forpliktelser blir lagret på den nye grenen. Du kan tenke på å sjekke ut en filial som å bytte til en ny prosjektmappe - bortsett fra at det blir mye lettere å trekke endringer tilbake i prosjektet.
Med dette i tankene er det vanligvis en god ide å ha en ren arbeidskatalog før du sjekker ut en filial. En ren katalog finnes når det ikke er noen ubestemte endringer. Hvis dette ikke er tilfelle, git kassen
har potensial til å overskrive dine modifikasjoner.
Som med å foreta en "sikker" revisjon, er du fri til å eksperimentere på en ny filial uten frykt for å ødelegge eksisterende funksjonalitet. Men du har nå en dedikert historie å jobbe med, slik at du kan registrere fremdriften av et eksperiment ved å bruke nøyaktig samme git add
og git commit
kommandoer fra tidligere i boken.
Denne funksjonaliteten vil bli enda sterkere når vi lærer å slå sammen divergerende historier tilbake til "hovedgrenen" (f.eks., herre
). Vi kommer til det i et øyeblikk, men først, det er en viktig bruk sak av git kassen
det må vurderes ...
Git lar deg også bruke git kassen
med tagger og forplikte IDer, men gjør det setter deg i en frittliggende HEAD-tilstand. Dette betyr at du ikke er på en gren lenger - du ser direkte på en forpliktelse.
Du kan se deg rundt og legge til nye forpliktelser som vanlig, men siden det ikke er noen gren som peker på tilleggene, mister du alt arbeidet ditt så snart du bytter tilbake til en ekte gren. Heldigvis oppretter en ny avdeling i en frittliggende HODE
staten er lett nok:
git checkout -b
Dette er en snarvei for git grenen
etterfulgt av git kassen
. Etter det vil du ha en skinnende ny grenreferanse til det tidligere frittliggende HODE
. Dette er en veldig praktisk prosedyre for forking eksperimenter av gamle revisjoner.
Fusjon er prosessen med å trekke forplikter seg fra en gren til en annen. Det er mange måter å kombinere grener på, men målet er alltid å dele informasjon mellom grener. Dette gjør det mulig å slå sammen en av de viktigste funksjonene i Git. De to vanligste metodene for sammenslåing er:
De bruker begge samme kommando, git fusjon
, men metoden bestemmes automatisk basert på strukturen i historien din. I hvert tilfelle, Avdelingen du vil smelte sammen må sjekkes ut, og målbrettet vil forbli uendret. De neste to seksjonene presenterer to mulige sammenføyningsscenarier for følgende kommandoer:
git checkout master git fusjonere noen-funksjonen
Igjen, dette fusjonerer noen-feature
grenen inn i herre
gren, forlater den tidligere uberørt. Du vil vanligvis kjøre disse kommandoene når du har fullført en funksjon og vil integrere den i det stabile prosjektet.
Det første scenariet ser slik ut:
Vi opprettet en filial for å utvikle ny funksjon, lagt til to forpliktelser, og nå er den klar til å bli integrert i hovedkoden. I stedet for å skrive om de to begår mangler fra herre
, Git kan "spole frem" på herre
grenens peker for å matche plasseringen av noen-feature
.
Etter fusjonen, herre
gren inneholder all ønsket historie, og funksjonen grenen kan bli slettet (med mindre du vil fortsette å utvikle den). Dette er den enkleste typen sammenslåing.
Selvfølgelig kunne vi ha gjort de to begår direkte på herre
gren; Men ved hjelp av en dedikert funksjonstjeneste fikk vi et trygt miljø for å eksperimentere med ny kode. Hvis det ikke viste seg riktig, kunne vi bare ha slettet grenen (i motsetning til tilbakestilling / tilbakestilling). Eller, hvis vi legger til en haug med mellomliggende forpliktelser som inneholder ødelagt kode, kan vi rydde den opp før den smelter sammen herre
(se Tilbakestilling under). Da prosjekter blir mer kompliserte og får flere samarbeidspartnere, gjør denne typen forgrenet utvikling Git et fantastisk organisasjonsverktøy.
Men ikke alle situasjoner er enkle nok for en fast-forward-forpliktelse. Husk at den største fordelen med grener er muligheten til å utforske mange uavhengige utviklingslinjer samtidig. Som et resultat vil du ofte møte et scenario som ser ut som følgende:
Dette startet som en hurtigspoling, men vi la til en forpliktelse til herre
gren mens vi fortsatt utviklet seg noen-feature
. For eksempel kunne vi ha sluttet å jobbe med funksjonen for å fikse en tidsfølsom feil. Selvfølgelig bør bug-fix legges til hovedregisteret så snart som mulig, så vi kommer opp i scenariet som er vist ovenfor.
Slå sammen funksjonstakten i herre
i denne sammenhengen resulterer i en "3-veis" -fusjon. Dette oppnås ved å bruke nøyaktig samme kommandoer som farten fremover fra forrige seksjon.
Git kan ikke spole fremover herre
pekeren til noen-feature
uten backtracking. I stedet genererer det en ny fusjonere forpliktelse som representerer det kombinerte øyeblikksbildet for begge grenene. Vær oppmerksom på at denne nye forpliktelsen har to Forelder forplikter seg, og gir den tilgang til begge historier (faktisk, kjører git logg
etter at 3-veis-fusjonen viser begår fra begge grener).
Navnet på denne sammenslåingsalgoritmen stammer fra den interne metoden som brukes til å opprette sammenslåingsforbindelsen. Git ser på tre forplikter seg til å generere den endelige tilstanden til sammenslåingen.
Hvis du prøver å kombinere to grener som gjør forskjellige endringer i samme del av koden, vet Git ikke hvilken versjon som skal brukes. Dette kalles a slå sammen konflikt. Tydeligvis kan dette aldri skje under en farten fremover. Når Git møter en fusjonskonflikt, ser du følgende melding:
Automatisk sammenslåing index.html KONFLIKT (innhold): Slå sammen konflikt iAutomatisk sammenføying mislyktes; fikse konflikter og deretter begå resultatet.
I stedet for å automatisk legge til fusjonen, stopper Git og spør deg hva du skal gjøre. Løping git status
i denne situasjonen kommer tilbake noe som følger:
# På grenmester # Unmerged baner: # # begge modifisert:
Hver fil med konflikt lagres under delen Unmerged paths. Git annoterer disse filene for å vise innholdet fra begge versjoner:
<<<<<<< HEAD This content is from the current branch. ======= This is a conflicting change from another branch. >>>>>>> noen-funksjon
Delen før =======
er fra herre
gren, og resten er fra grenen du prøver å integrere.
For å løse konflikten, fjern <<<<<<
, =======
, og >>>>>>>
notat, og endre koden til det du vil beholde. Så, fortell Git, du er ferdig med å løse konflikten med git add
kommando:
git add
Det er riktig; alt du trenger å gjøre er å arrangere den konfliktede filen for å markere den som løst. Endelig fullfør 3-veis flette ved å generere sammenslåingsplikten:
git commit
Logmeldingen er seeded med en fusjonssammenheng, sammen med en "konflikt" -liste, som kan være spesielt nyttig når man prøver å finne ut hvor noe gikk galt i et prosjekt.
Og det er alt der er å slå sammen i Git. Nå som vi har en forståelse av mekanikken bak Git-grener, kan vi ta en grundig titt på hvordan veteran Git-brukere utnytter grener i hverdagen sin.
Arbeidsflytene som presenteres i denne delen er kjennetegnet for Git-basert revisjonskontroll. Den lettvektige, enkle kombinasjonen av Gits grensesnittimplementasjon gjør dem til et av de mest produktive verktøyene i din programvareutvikling arsenal.
Alle forgrenings arbeidsflyter dreier seg rundt git grenen
, git kassen
, og git fusjon
kommandoer presentert tidligere dette kapittelet.
Det er ofte nyttig å tilordne spesiell betydning til forskjellige grener for å organisere et prosjekt. Denne delen introduserer de vanligste typene av grener, men husk at disse forskjellene er rent overfladiske - til Git, en filial er en gren.
Alle grener kan kategoriseres som enten fast grener eller emne grener. Den tidligere inneholder hovedprosjektets historie (f.eks., herre
), mens sistnevnte er midlertidige grener som brukes til å implementere en bestemt emne, deretter kasseres (f.eks., noen-feature
).
Permanente grener er livsnerven i noe lager. De inneholder alle viktige veipunkter for et programvareprosjekt. De fleste utviklere bruker herre
utelukkende for stabil kode. I disse arbeidsflytene, deg aldri forplikte seg direkte herre
-Det er bare en integrasjonsgren for ferdige funksjoner som ble bygget i dedikerte emner.
I tillegg legger mange brukere til et andre lag av abstraksjon i en annen integrasjonsgren (konvensjonelt kalt utvikle
, selv om et navn vil være nok). Dette frigjør herre
gren for egentlig stabil kode (for eksempel offentlig forpliktelse) og bruk utvikle
som en intern integrasjonsgren for å forberede en offentlig utgivelse. For eksempel viser følgende diagram at flere funksjoner er integrert i utvikle
, så en enkelt, endelig fusjonere inn herre
, som symboliserer en offentlig utgivelse.
herre
gren utelukkende for offentliggjøring Emnet grener faller vanligvis i to kategorier: funksjonen grener og hurtigreparasjonsgrener. Funksjonsgrener er midlertidige grener som innkapsler en ny funksjon eller refaktor, og beskytter hovedprosjektet fra uprøvd kode. De stammer vanligvis fra en annen filial eller en integrasjonsgren, men ikke den "super stabile" grenen.
Hurtigreparasjonsgrener er av samme art, men de stammer fra publiseringsgrenen (f.eks., herre
). I stedet for å utvikle nye funksjoner, er de for å raskt lappe hovedlinjen for utvikling. Vanligvis betyr dette feilrettinger og andre viktige oppdateringer som ikke kan vente til neste store utgivelse.
herre
med en hurtigreparasjonsgrense Igjen er betydningen som er tildelt hver av disse grenene rent konvensjonelle, Git ser ingen forskjell mellom herre
, utvikle
, funksjoner og hurtigreparasjoner. Med det i tankene, vær ikke redd for å tilpasse dem til dine egne ender. Gitas skjønnhet er dens fleksibilitet. Når du forstår mekanikken bak Git-grener, er det enkelt å designe nye arbeidsflyter som passer ditt prosjekt og din personlighet.
Å gjenopprette er prosessen med å flytte en gren til en ny utgangspunkt. Gits gjenoppbyggingsmuligheter gjør filialene enda mer fleksible ved å la brukerne manuelt organisere sine grener. Som å slå sammen, git rebase
krever at grenen blir sjekket ut og tar den nye basen som et argument:
git checkout noen-funksjon git rebase master
Dette beveger seg hele noen-feature
gren på spissen av herre
:
noen-feature
på herre
gren Etter gjenstanden er funksjonen grenen en lineær forlengelse av herre
, som er en mye renere måte å integrere endringer fra en gren til en annen. Sammenlign denne lineære historien med en sammenslåing av herre
inn i noen-feature
, som resulterer i nøyaktig samme kodebase i det endelige stillbildet:
herre
inn i noen-feature
med en 3-veis flette Siden historien har avviklet, må Git bruke en ekstra fletteforpliktelse for å kombinere grenene. Å gjøre dette mange ganger i løpet av utviklingen av en langvarig funksjon kan resultere i en veldig rotete historie.
Disse ekstra fletteforpliktelsene er overflødige - de eksisterer bare for å trekke endringer fra herre
inn i noen-feature
. Vanligvis vil du ha sammenføyning til deg mener noe som å fullføre en ny funksjon. Derfor velger mange utviklere å trekke i endringer med git rebase
, siden det resulterer i en helt lineær historie i funksjonen grenen.
Interaktiv gjenoppretting går et skritt videre og lar deg endring forplikter seg når du flytter dem til den nye basen. Du kan angi en interaktiv tilbakemelding med -Jeg
flagg:
git rebase -i master
Dette fyller i en tekstredigerer med et sammendrag av hver commit i funksjonen grenen, sammen med en kommando som bestemmer hvordan Det skal overføres til den nye basen. Hvis du for eksempel har to forpliktelser på en funksjonavdeling, kan du spesifisere en interaktiv rabatt som følgende:
velg 58dec2a Først forplikte for ny funksjonskamp 6ac8a9f For det andre forplikte seg til ny funksjon
Standaren plukke
kommandoen beveger den første forpliktelsen til den nye basen som den normale git rebase
, men da squash
kommandoen forteller Git å kombinere den andre forplikten med den forrige, slik at du slutter med en forpliktelse som inneholder alle dine endringer:
noen-feature
gren Git gir flere interaktive gjenopprettingskommandoer, som hver er oppsummert i kommentarseksjonen i konfigurasjonslisten. Poenget er interaktiv gjenoppretting lar deg helt omskrive en grenses historie til dine eksakte spesifikasjoner. Dette betyr at du kan legge til så mange mellomliggende forpliktelser til en funksjonavdeling som du trenger, og deretter gå tilbake og fikse dem til meningsfylt progresjon etter det faktum.
Andre utviklere vil tro at du er en strålende programmerer, og visste nøyaktig hvordan du skal implementere hele funksjonen i ett fall. Denne typen organisasjon er svært viktig for å sikre at store prosjekter har en navigerbar historie.
Å gjenopprette er et kraftig verktøy, men du må være dømmende når du skriver om historien. Begge typer gjenoppretting egentlig ikke bevege seg eksisterende forpliktelser-de skape helt nye (betegnet med en stjerne i diagrammet ovenfor). Hvis du inspiserer forpliktelser som ble utsatt for en tilbakebetaling, vil du legge merke til at de har forskjellige IDer, selv om de representerer det samme innholdet. Dette innebærer gjenoppretting ødelegger eksisterende forplikter seg i prosessen med å "flytte" dem.
Som du kanskje tror, har dette dramatiske konsekvenser for samarbeidsprosesser. Å ødelegge en offentlig forpliktelse (for eksempel noe på herre
gren) er som å rive ut grunnlaget for alles andres arbeid. Git har ingen anelse om hvordan du kan kombinere alles endringer, og du vil ha mange unnskyldninger å gjøre. Vi tar en mer grundig titt på dette scenariet etter at vi lærer å kommunisere med eksterne repositorier.
For nå, bare overholde den gylne regelen om å rebase: Ikke motta en gren som har blitt presset til et offentlig lager.
Denne leksjonen representerer et kapittel fra Git Succinctly, en gratis eBok fra teamet på Syncfusion.