La oss si at vi har følgende situasjon i Git:
Et opprettet depot:
mkdir GitTest2
cd GitTest2
git init
Noen endringer i masteren finner sted og blir forpliktet.
echo "På Master" > fil
git commit -a -m "Initial commit"
Feature1 forgrenet master og noe arbeid er gjort:
git branch feature1
git checkout feature1
echo "Feature1" > featureFile
git commit -a -m "Commit for feature1"
I mellomtiden oppdages en feil i hovedkoden, og en hotfix-gren opprettes.
git checkout master
git branch hotfix1
git checkout hotfix1
Feilen rettes i hotfix-grenen og flettes tilbake til masteren (kanskje etter en pull-forespørsel/kodegjennomgang):
echo "Bugfix" > bugfixFile
git commit -a -m "Bugfix Commit"
git checkout master
git merge --no-off hotfix1
Utviklingen på feature1 fortsetter:
git checkout feature1
Si at jeg trenger hurtigreparasjonen i funksjonsgrenen min, kanskje fordi feilen også oppstår der. Hvordan kan jeg oppnå dette uten å duplisere commits i funksjonsgrenen min?
Jeg vil forhindre å få to nye forpliktelser på funksjonsgrenen min som ikke har noen relasjon til funksjonsimplementeringen. Dette virker spesielt viktig for meg hvis jeg bruker pull-forespørsler: Alle disse forpliktelsene vil også bli inkludert i pull-forespørselen og må gjennomgås selv om dette allerede er gjort (ettersom hotfixen allerede er i masteren).
Jeg kan ikke gjøre en git merge master --ff-only
: "fatal: Ikke mulig å spole fremover, avbryte.", men jeg er ikke sikker på om dette hjalp meg.
Hvordan fletter vi hovedgrenen inn i funksjonsgrenen? Enkelt:
git checkout feature1
git merge master
Det er ikke noe poeng i å tvinge en rask fletting fremover her, da det ikke kan gjøres. Du forpliktet deg både til funksjonsgrenen og hovedgrenen. Spoling fremover er umulig nå.
Ta en titt på GitFlow. Det er en forgreningsmodell for git som kan følges, og det har du ubevisst allerede gjort. Det er også en utvidelse til Git som legger til noen kommandoer for de nye trinnene i arbeidsflyten som gjør ting automatisk som du ellers må gjøre manuelt.
Så hva gjorde du riktig i arbeidsflyten din? Du har to grener å jobbe med, din feature1-gren er i utgangspunktet "develop" -grenen i GitFlow-modellen.
Du opprettet en hotfix-gren fra master og flettet den tilbake. Og nå sitter du fast.
GitFlow-modellen ber deg om å slå sammen hotfixen også til utviklingsgrenen, som er "feature1" i ditt tilfelle.
Så det virkelige svaret ville være:
git checkout feature1
git merge --no-ff hotfix1
Dette legger til alle endringene som ble gjort i hurtigrettingen i funksjonsgrenen, men bare disse endringene. De kan komme i konflikt med andre utviklingsendringer i grenen, men de vil ikke komme i konflikt med hovedgrenen hvis du fletter funksjonsgrenen tilbake til hovedgrenen til slutt.
Vær veldig forsiktig med rebasering. Rebase bare hvis endringene du gjorde forble lokale til depotet ditt, f.eks. at du ikke dyttet noen grener til et annet depot. Rebasing er et flott verktøy for deg til å ordne dine lokale commits i en nyttig rekkefølge før du skyver det ut i verden, men å rebasere etterpå vil ødelegge ting for git nybegynnere som deg.
Du bør være i stand til å basere filialen din på master:
git checkout feature1
git rebase master
Håndter alle konflikter som oppstår. Når du kommer til commits med feilrettingene (allerede i master), vil Git si at det ikke var noen endringer og at de kanskje allerede var brukt. Du fortsetter deretter ombaseringen (mens du hopper over commitene som allerede er i master) med
git rebase --skip
Hvis du utfører en git-logg
på funksjonsgrenen din, vil du se at feilrettingsforbindelsen bare vises en gang, og i master-delen.
For en mer detaljert diskusjon, ta en titt på Git-bokdokumentasjonen om git rebase
(https://git-scm.com/docs/git-rebase) som dekker akkurat dette brukstilfellet.
================ Rediger for ytterligere kontekst ====================
Dette svaret ble gitt spesielt for spørsmålet som ble stilt av @theomega, med tanke på hans spesielle situasjon. Legg merke til denne delen:
Jeg vil forhindre [...] forpliktelser på funksjonsgrenen min som ikke har noen relasjon til funksjonsimplementeringen.
Å basere hans private gren på master er akkurat det som vil gi det resultatet. Derimot vil sammenslåing av master i grenen hans gjøre nettopp det han spesifikt ikke ønsker skal skje: å legge til en commit som ikke er relatert til funksjonsimplementeringen han jobber med via grenen sin.
For å henvende meg til brukerne som leser spørsmålstittelen, hopper over det faktiske innholdet og konteksten til spørsmålet, og deretter bare leser det øverste svaret blindt og antar at det alltid vil gjelde for deres (forskjellige) brukstilfelle, la meg utdype:
git merge master
som i @Svens svar).Til slutt, hvis du er misfornøyd med det faktum at dette svaret ikke passer best for din situasjon, selv om det var for @theomega, vil det ikke være spesielt nyttig å legge til en kommentar nedenfor: Jeg kontrollerer ikke hvilket svar som velges, det er det bare @theomega som gjør.
Du kan kanskje gjøre en "cherry-pick" for å trekke de nøyaktige commit(ene) du trenger inn i funksjonsgrenen din.
Gjør en git checkout hotfix1
for å komme på hotfix1-grenen. Gjør deretter en git log
for å få SHA-1-hash (stor sekvens av tilfeldige bokstaver og tall som unikt identifiserer en commit) av den aktuelle commit. Kopier det (eller de første 10 tegnene eller så).
Deretter, git checkout feature1
for å komme tilbake til funksjonsgrenen din.
Deretter, git cherry-pick <SHA-1 hash som du nettopp kopierte >
Det vil trekke den overføringen, og bare den overføringen, inn i funksjonsgrenen din. Denne endringen vil være i grenen - du bare "kirsebærplukket" den inn. Fortsett deretter arbeidet, rediger, commit, push, etc. til ditt hjerte&# 39s innhold.
Når du til slutt utfører en annen sammenslåing fra en gren til funksjonsgrenen din (eller omvendt), vil Git gjenkjenne at du allerede har slått sammen i den aktuelle commit, vet at den ikke trenger å gjøre det igjen, og bare "hoppe over" den.