-
1. Kom igång
- 1.1 Om versionshantering
- 1.2 En kort historik om Git
- 1.3 Vad är Git?
- 1.4 Kommandoraden
- 1.5 Installera Git
- 1.6 Första gången med Git
- 1.7 Få hjälp
- 1.8 Sammanfattning
-
2. Grunderna i Git
- 2.1 Att få tag i ett Git‑kodförråd
- 2.2 Spara ändringar i kodförrådet
- 2.3 Visa incheckningshistoriken
- 2.4 Ångra saker
- 2.5 Arbeta med fjärrkodförråd
- 2.6 Att tagga
- 2.7 Git-alias
- 2.8 Sammanfattning
-
3. Git-grenar
- 3.1 Grenar i korthet
- 3.2 Grundläggande gren- och sammanfogningsarbete
- 3.3 Grenhantering
- 3.4 Arbetsflöden med grenar
- 3.5 Fjärrgrenar
- 3.6 Ombasering
- 3.7 Sammanfattning
-
4. Git på servern
- 4.1 Protokollen
- 4.2 Konfigurera Git på en server
- 4.3 Generera din publika SSH-nyckel
- 4.4 Konfigurera servern
- 4.5 Git-demon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Tredjepartsalternativ
- 4.10 Sammanfattning
-
5. Distribuerat Git
-
6. GitHub
-
7. Git-verktyg
- 7.1 Revisionsurval
- 7.2 Interaktiv köläggning
- 7.3 Lägga undan och städa
- 7.4 Signera ditt arbete
- 7.5 Sökning
- 7.6 Skriva om historik
- 7.7 Nollställning förklarad
- 7.8 Avancerad sammanslagning
- 7.9 Rerere
- 7.10 Felsöka med Git
- 7.11 Undermoduler
- 7.12 Bunta
- 7.13 Ersätt
- 7.14 Lagring av inloggningsuppgifter
- 7.15 Sammanfattning
-
8. Anpassa Git
- 8.1 Git‑konfiguration
- 8.2 Git‑attribut
- 8.3 Git‑krokar
- 8.4 Ett exempel på Git‑upprätthållen policy
- 8.5 Sammanfattning
-
9. Git och andra system
- 9.1 Git som klient
- 9.2 Migrera till Git
- 9.3 Sammanfattning
-
10. Git bakom kulisserna
- 10.1 Lågnivådel och användardel
- 10.2 Git-objekt
- 10.3 Git-referenser
- 10.4 Packfiler
- 10.5 Refspecen
- 10.6 Överföringsprotokoll
- 10.7 Underhåll och dataåterställning
- 10.8 Miljövariabler
- 10.9 Sammanfattning
-
A1. Bilaga A: Git i andra miljöer
- A1.1 Grafiska gränssnitt
- A1.2 Git i Visual Studio
- A1.3 Git i Visual Studio Code
- A1.4 Git i IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git i Sublime Text
- A1.6 Git i Bash
- A1.7 Git i Zsh
- A1.8 Git i PowerShell
- A1.9 Sammanfattning
-
A2. Bilaga B: Bädda in Git i dina applikationer
- A2.1 Git på kommandoraden
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Bilaga C: Git-kommandon
- A3.1 Uppstart och konfiguration
- A3.2 Skaffa och skapa projekt
- A3.3 Grundläggande ögonblicksbilder
- A3.4 Grening och sammanslagning
- A3.5 Dela och uppdatera projekt
- A3.6 Inspektion och jämförelse
- A3.7 Felsökning
- A3.8 Patchning
- A3.9 E‑post
- A3.10 Externa system
- A3.11 Administration
- A3.12 Lågnivåkommandon
5.2 Distribuerat Git - Bidra till ett projekt
Bidra till ett projekt
Det svåra med att beskriva hur du gör för att bidra till ett projekt är att medverkan kan ske på mängder av olika sätt. Tack vare Gits flexibilitet skiljer sig användningen åt, vilket gör det näst intill omöjligt att säga hur du borde göra – varje projekt arbetar på sitt sätt. Faktorer som påverkar hur ett projekt är organiserat är antalet aktivt involverade, överenskomna arbetsprocesser och fördelningen av behörigheter för att checka in kod. Det finns dock några generella riktlinjer som kan hjälpa dig att komma igång.
För det första – hur många involverade bidrar aktivt med källkod och hur ofta? I mindre projekt är det vanligt att ett par, tre utvecklare gör några få incheckningar om dagen, kanske ännu färre om projektet är vilande. I större projekt, eller organisationer för den delen, kan hundratals utvecklare arbeta aktivt med kodbasen och bidra med tusentals incheckningar varje dag.
Det är viktigt att känna till ungefär hur många som arbetar aktivt i kodbasen. Ju fler utvecklare, desto fler problem kan du stöta på för att få din kod att läggas till och integreras smidigt. Under tiden du arbetar med dina ändringar, eller väntar på att få dem godkända, kan ny kod göra dem icke-funktionella – eller rentav inaktuella. Hur kan du då göra för att din egen kodbas ska hållas uppdaterad och dina incheckningar aktuella?
För det andra, hur ser projektets beslutade arbetsprocess ut? Är det en centraliserad process, så att varje utvecklare har samma skrivrättigheter till koden på huvudgrenen? Har projektet en förvaltare eller integrationsansvarig som granskar alla ändringar? Ska alla ändringar granskas och godkännas av en annan utvecklare? Kommer du att vara involverad i den processen? Eller finns det ett kvalitetssystem med testare på plats som du behöver skicka dina ändringar till först?
Till sist spelar behörigheter för incheckningar in. Din medverkan kommer att skilja sig mycket åt beroende på om du har skrivrättigheter till kodbasen eller inte. Om du inte har det, hur ser processen ut för att granska och godkänna bidrag? Finns det ens en sådan process? Hur många ändringar ska skickas med i taget? Hur ofta?
Alla dessa frågor påverkar hur du bäst bidrar till ett projekt, liksom vilka arbetssätt du själv föredrar eller har tillgång till. Vi kommer att gå igenom tillvägagångssätten ur olika aspekter i en serie användarfall, från enkla till mer komplexa. Du borde känna igen det arbetssätt du förväntas använda i dessa exempel.
Riktlinjer för incheckningar
Innan vi går in på användarfallen kommer en kort kommentar om incheckningsmeddelanden.
Att ha bra riktlinjer för incheckningar, och att hålla sig till dem, gör det betydligt enklare att använda Git tillsammans med andra.
I Git‑projektet finns ett dokument med flera bra tips på saker att tänka på för att göra incheckningar till en ändringsserie.
Du hittar det i filen Documentation/SubmittingPatches i Gits källkod.
Först av allt bör dina bidrag inte ha några felaktiga mellanslag.
Git har ett enkelt sätt att kontrollera det – innan du gör en incheckning, kör kommandot git diff --check.
Det ger dig en lista över möjliga mellanslag som kan vara felaktiga.
git diff --check
Kör kommandot innan en incheckning för att snabbt kontrollera om du är på väg att checka in mellanslag som kan irritera andra utvecklare.
För det andra, försök att göra varje incheckning till en logiskt separat enhet.
Om du kan, försök att hålla dina ändringar lättsmälta – koda inte en hel helg på fem olika uppgifter för att sedan skicka dem som en enda gigantisk incheckning på måndag.
Även om du inte har checkat in på en hel helg, använd köytan för att dela upp ditt arbete i flera incheckningar på måndagen, med ett tydligt meddelande per incheckning.
Om några av ändringarna är i samma fil, försök att använda git add --patch för att delvis köa filer (läs mer i Interaktiv köläggning).
Projektets ögonblicksbild längst ut på grenen kommer att se likadan ut oavsett om du gör en incheckning eller fem, så länge alla ändringar läggs till förr eller senare.
Försök därför att göra det så enkelt som möjligt för dina kollegor när de ska granska dina ändringar.
Med det tillvägagångssättet blir det också enklare att dra ut eller återställa någon av ändringarna i efterhand, om det skulle behövas. I avsnittet Skriva om historik finns en mängd användbara tips för att skriva om Git‑historiken och interaktivt köa filer – använd dessa verktyg för att få en logisk och förståelig historik innan du skickar arbetet vidare till någon annan.
Slutligen behövs en struktur för incheckningsmeddelandet. Med vanan att alltid skriva bra meddelanden blir användningen av – och samarbetet i – Git betydligt enklare. Tumregeln är att dina meddelanden ska börja med en mening på max 50 tecken som sammanfattar ändringen, följt av en blank rad och en mer detaljerad beskrivning. Git‑projektet menar att beskrivningen bör inkludera anledningen till ändringen och en jämförelse med tidigare beteende – det är en bra riktlinje att följa. Det är också bra att skriva i imperativ form. Med andra ord, ge order. I stället för "Jag lade till test för" eller "Lägger till test för" skriver du "Lägg till test för". Här är en mall ursprungligen skriven av Tim Pope:
Capitalized, short (50 chars or less) summary
More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body. The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase will confuse you if you run the
two together.
Write your commit message in the imperative: "Fix bug" and not "Fixed bug"
or "Fixes bug." This convention matches up with commit messages generated
by commands like git merge and git revert.
Further paragraphs come after blank lines.
- Bullet points are okay, too
- Typically a hyphen or asterisk is used for the bullet, followed by a
single space, with blank lines in between, but conventions vary here
- Use a hanging indent
Om alla dina incheckningsmeddelanden följer den här mallen blir det lättare, både för dig och dem du samarbetar med.
Git‑projektet har välformaterade incheckningsmeddelanden – kör git log --no-merges där för att få inspiration till hur en välformaterad incheckningshistorik kan se ut.
|
Notera
|
Gör som vi säger och inte som vi gör
För att vara helt ärliga har många av exemplen i den här boken inte särskilt välformaterade incheckningsmeddelanden; vi använder ofta Som sagt, gör som vi säger, inte som vi gör. |
Privat, litet team
Det enklaste arbetssättet du sannolikt kommer stöta på är ett privat projekt med en eller två utvecklare. I den här kontexten betyder "privat" sluten källkod – den är inte tillgänglig för utomstående. Du och de andra utvecklarna har skrivrättigheter till kodförrådet.
I den här uppsättningen liknar arbetssättet det som du kanske stöter på när du använder Subversion eller något annat centraliserat versionshanteringssystem. Du behåller fördelar som att kunna checka in utan uppkoppling och att ha enkel grenhantering, men arbetsprocessen är mycket lik; den största skillnaden är att sammanslagningar sker i klienten i stället för på servern vid incheckning.
# John's Machine
$ git clone john@githost:simplegit.git
Cloning into 'simplegit'...
...
$ cd simplegit/
$ vim lib/simplegit.rb
$ git commit -am 'Remove invalid default value'
[master 738ee87] Remove invalid default value
1 files changed, 1 insertions(+), 1 deletions(-)
...
$ cd simplegit/
$ vim lib/simplegit.rb
$ git commit -am 'remove invalid default value'
[master 738ee87] remove invalid default value
1 files changed, 1 insertions(+), 1 deletions(-)
# Jessica's Machine
$ git clone jessica@githost:simplegit.git
Cloning into 'simplegit'...
...
$ cd simplegit/
$ vim TODO
$ git commit -am 'Add reset task'
[master fbff5bc] Add reset task
1 files changed, 1 insertions(+), 0 deletions(-)
...
$ cd simplegit/
$ vim TODO
$ git commit -am 'add reset task'
[master fbff5bc] add reset task
1 files changed, 1 insertions(+), 0 deletions(-)
Sedan skickar Jessica upp sina ändringar till servern, vilket går bra:
# Jessica's Machine
$ git push origin master
...
To jessica@githost:simplegit.git
1edee6b..fbff5bc master -> master
Den sista raden i utdata är ett nyttigt meddelande.
Formateringen är <gammalref>..<nyref> frånref → tillref, där gammalref betyder tidigare referens, nyref är den nya referensen, frånref är den lokala referens som ändringen kommer från och tillref är fjärrreferensen som har uppdaterats.
Du kommer att se liknande utdata i exemplen nedan; en grundförståelse gör det lättare att tolka kodförrådets olika lägen.
# John's Machine
$ git push origin master
To john@githost:simplegit.git
! [rejected] master -> master (non-fast forward)
error: failed to push some refs to 'john@githost:simplegit.git'
I det här fallet kan John inte skicka sina incheckningar på grund av Jessicas tidigare incheckning. Det här är särskilt viktigt att förstå om du tidigare har använt Subversion – du kommer att märka att de två utvecklarna inte ändrade i samma fil. Subversion sammanfogar automatiskt på servern om olika filer har ändrats, men i Git måste du själv först sammanfoga incheckningarna lokalt.
$ git fetch origin
...
From john@githost:simplegit
+ 049d078...fbff5bc master -> origin/master
Johns kodförråd ser nu ut ungefär så här:
$ git merge origin/master
Merge made by the 'recursive' strategy.
TODO | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
Om den lokala sammanslagningen går smidigt kommer Johns uppdaterade historik se ut ungefär så här:
origin/master
Nu kanske John vill testa den nya koden för att vara helt säker på att ingen av Jessicas ändringar påverkat hans, och om allt går bra kan han skicka sina sammanfogade ändringar till servern:
$ git push origin master
...
To john@githost:simplegit.git
fbff5bc..72bbc59 master -> master
Till sist ser Johns incheckningshistorik ut så här:
origin
Under tiden har Jessica skapat en ny gren med namnet issue54 och gjort tre incheckningar till den nya grenen.
Hon har inte uppdaterat Johns ändringar än, så hennes historik ser ut så här:
# Jessica's Machine
$ git fetch origin
...
From jessica@githost:simplegit
fbff5bc..72bbc59 master -> origin/master
Nu uppdateras Johns incheckade ändringar. Jessicas historik kommer att se ut så här:
$ git log --no-merges issue54..origin/master
commit 738ee872852dfaa9d6634e0dea7a324040193016
Author: John Smith <jsmith@example.com>
Date: Fri May 29 16:01:27 2009 -0700
Remove invalid default value
Syntaxen issue54..origin/master används för att filtrera loggar.
Git ombeds att bara visa de incheckningar i den senare referensen (origin/master) som inte finns på den första referensen (här issue54).
Vi går igenom syntaxen i detalj i Incheckningsintervall.
Utifrån ovan ser vi att det bara är en enda av Johns incheckningar som Jessica inte har sammanfogat lokalt.
Om hon sammanfogar sina ändringar med origin/master är det bara den incheckningen som påverkar hennes lokala kodförråd.
$ git checkout master
Switched to branch 'master'
Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
$ git merge issue54
Updating fbff5bc..4af4298
Fast forward
README | 1 +
lib/simplegit.rb | 6 +++++-
2 files changed, 6 insertions(+), 1 deletions(-)
$ git merge origin/master
Auto-merging lib/simplegit.rb
Merge made by the 'recursive' strategy.
lib/simplegit.rb | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
Allt slogs ihop utan problem, Jessicas historik ser nu ut så här:
Fjärrreferensen origin/master kan nås från Jessicas huvudgren, så hon borde kunna skicka utan problem (förutsatt att John inte har skickat fler ändringar under tiden):
$ git push origin master
...
To jessica@githost:simplegit.git
72bbc59..8059c15 master -> master
Båda utvecklarna har nu checkat in sina versioner av filerna några gånger och fått in varandras ändringar i sina lokala kodbaser.
Det här är en av de enklaste arbetsprocesserna.
Du arbetar ett tag (ofta i en funktionsgren) och sammanfogar arbetet i huvudgrenen när det är klart.
När du vill dela ditt arbete uppdaterar du och sammanfogar din huvudgren med origin/master och skickar tillbaka din huvudgren till servern.
Den generella arbetsprocessen ser ut så här:
Privat större team
Nästa exempel gäller ett större, privat team. Här tittar vi på hur arbetsprocessen kan se ut när mindre team samarbetar på funktioner som sedan sammanfogas av andra team.
Säg att John och Jessica arbetar tillsammans på en funktion (vi kallar den "featureA"). Samtidigt samarbetar Jessica och en tredje utvecklare, Josie, på en annan ("featureB"). I det här fallet använder organisationen ett integrationsstyrt arbetsflöde där arbetet från ett enskilt team sammanfogas med huvudgrenen av särskilda ingenjörer. Huvudgrenen kan endast uppdateras av dessa. Allt arbete sker i grenar som sedan sammanfogas senare.
# Jessica's Machine
$ git checkout -b featureA
Switched to a new branch 'featureA'
$ vim lib/simplegit.rb
$ git commit -am 'Add limit to log function'
[featureA 3300904] Add limit to log function
1 files changed, 1 insertions(+), 1 deletions(-)
I det här läget behöver hon dela arbetet med John, så hon skickar sin featureA-gren till servern.
Jessica har inte behörighet att sammanfoga i huvudgrenen, så hon måste skicka till en separat gren för att kunna samarbeta:
$ git push -u origin featureA
...
To jessica@githost:simplegit.git
* [new branch] featureA -> featureA
# Jessica's Machine
$ git fetch origin
$ git checkout -b featureB origin/master
Switched to a new branch 'featureB'
$ vim lib/simplegit.rb
$ git commit -am 'Make ls-tree function recursive'
[featureB e5b0fdc] Make ls-tree function recursive
1 files changed, 1 insertions(+), 1 deletions(-)
$ vim lib/simplegit.rb
$ git commit -am 'Add ls-files'
[featureB 8512791] Add ls-files
1 files changed, 5 insertions(+), 0 deletions(-)
Jessicas kodförråd ser nu ut så här:
$ git fetch origin
...
From jessica@githost:simplegit
* [new branch] featureBee -> origin/featureBee
$ git merge origin/featureBee
Auto-merging lib/simplegit.rb
Merge made by the 'recursive' strategy.
lib/simplegit.rb | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
Nu vill Jessica skicka allt i featureB tillbaka till servern, men utan att skicka sin egen gren.
Eftersom Josie redan har en uppströmsgren featureBee vill Jessica skicka till den grenen.
Det gör hon så här:
$ git push -u origin featureB:featureBee
...
To jessica@githost:simplegit.git
fba9af8..cd685d1 featureB -> featureBee
Detta kallas en referensspecifikation.
Se Refspecen för mer information om referensspecifikationer.
Lägg också märke till -u; det är kort för --set-upstream och sparar vilken fjärrgren den lokala grenen spårar.
Plötsligt får Jessica ett e-postmeddelande från John, som berättar att han har skickat några ändringar till featureA och ber henne kolla på dem.
Återigen kör Jessica git fetch för att uppdatera allt nytt innehåll från servern, inklusive Johns senaste arbete:
$ git fetch origin
...
From jessica@githost:simplegit
3300904..aad881d featureA -> origin/featureA
Jessica kan nu läsa loggen med Johns senaste ändringar genom att jämföra det som uppdaterats för featureA med den lokala kopian av samma gren:
$ git log featureA..origin/featureA
commit aad881d154acdaeb2b6b18ea0e827ed8a6d671e6
Author: John Smith <jsmith@example.com>
Date: Fri May 29 19:57:33 2009 -0700
Increase log output to 30 from 25
Om Jessica gillar det hon ser kan hon sammanfoga Johns nya arbete till sin lokala featureA-gren med:
$ git checkout featureA
Switched to branch 'featureA'
$ git merge origin/featureA
Updating 3300904..aad881d
Fast forward
lib/simplegit.rb | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
Till sist kanske Jessica vill göra några mindre ändringar i det sammanfogade innehållet.
Hon har full frihet att göra sina ändringar, checka in dem i sin lokala featureA-gren och skicka slutresultatet till servern.
$ git commit -am 'Add small tweak to merged content'
[featureA 774b3ed] Add small tweak to merged content
1 files changed, 1 insertions(+), 1 deletions(-)
$ git push
...
To jessica@githost:simplegit.git
3300904..774b3ed featureA -> featureA
Jessicas incheckningshistorik kommer nu att se ut ungefär så här:
Vid någon tidpunkt behöver Jessica, John och Josie meddela de som ansvarar för huvudgrenen att featureA och featureB är redo att sammanfogas.
När sammanslagningen i huvudgrenen är klar kommer en uppdatering att ge den nya incheckningen.
Historiken ser då ut så här:
Många byter till Git på grund av möjligheten för flera team att arbeta parallellt och kombinera sina grenar sent i processen. Möjligheten att mindre grupper inom ett team kan samarbeta via fjärrgrenar utan att involvera hela teamet är en av Gits stora fördelar. Arbetsprocessen som precis beskrivits ser ut ungefär så här:
Öppet, litet projekt
Att bidra till öppna projekt är ofta lite annorlunda än privata. Eftersom du vanligtvis inte har behörighet att ändra direkt i projektet behöver förvaltarna få ditt arbete på något annat sätt. I det första exemplet tittar vi på hur man avgrenar ett kodförråd på värdtjänster som tillåter det. Många värdtjänster har stöd för avgreningar (till exempel GitHub, BitBucket, repo.or.cz) och många projektansvariga förväntar sig att andra medverkar på det sättet. Det andra exemplet beskriver arbetsprocessen i projekt som i stället föredrar att ta emot ändringspatchar via e-post.
Det första du behöver göra är troligen att klona grundkodförrådet och skapa en funktionsgren för ändringspatcharna du planerar att bidra med. Flödet ser ut så här:
$ git clone <url>
$ cd project
$ git checkout -b featureA
... work ...
$ git commit
... work ...
$ git commit
|
Notera
|
Du kanske vill använda |
När arbetet är klart och du vill dela det går du till grundkodförrådets projektsida och klickar på knappen "Avgrena" för att skapa en avgrening som du har full behörighet till.
Därefter lägger du till den nya kodförrådets URL som ett nytt fjärrkodförråd; i det här exemplet kallar vi den min-avgrening:
$ git remote add myfork <url>
Sedan behöver du skicka arbetet till avgreningen. Det är enklare att skicka funktionsgrenen du arbetar på till ditt kopierade kodförråd än att sammanfoga den i din huvudgren och skicka den. Om ditt arbete inte godkänns, eller om din incheckning inte blir handplockad, slipper du spola tillbaka din huvudgren (läs mer om handplockning i Arbetsflöden med ombasering och handplockning). Om förvaltarna sammanfogar, ombaserar eller handplockar din funktion får du ändå tillbaka den när du drar ner deras ändringar. Hur du än gör kan du skicka arbetet med:
$ git push -u myfork featureA
När ditt arbete har skickats till din avgrening behöver du meddela förvaltarna av originalprojektet att du har arbete du vill att de ska sammanfoga.
Det kallas ofta en ändringsförfrågan och du gör det antingen via webbsida – GitHub har sin egen mekanism som vi går igenom i GitHub – eller genom kommandot git request-pull och skickar utdatan via e-post.
Kommandot git request-pull tar basgrenen (den gren du vill att din funktionsgren dras in i) och URL:en till kodförrådet som ska acceptera koden, och sammanfattar ändringarna som ska tas in.
Om Jessica till exempel vill skicka en ändringsförfrågan till John och hon har gjort två incheckningar på funktionsgrenen hon just har skickat, kan hon göra så här:
$ git request-pull origin/master myfork
The following changes since commit 1edee6b1d61823a2de3b09c160d7080b8d1b3a40:
Jessica Smith (1):
Create new function
are available in the git repository at:
https://githost/simplegit.git featureA
Jessica Smith (2):
Add limit to log function
Increase log output to 30 from 25
lib/simplegit.rb | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
Den här utdatan kan skickas till förvaltarna – den beskriver från vilken gren arbetet avgrenades, sammanfattar incheckningarna och anger varifrån den nya funktionen kan uppdateras.
I ett projekt där du inte är ansvarig är det oftast enklast att ha en huvudgren, t.ex. master, som alltid följer origin/master och sedan arbeta i funktionsgrenar som du enkelt kan radera om de inte godkänns.
Att isolera funktioner i funktionsgrenar gör det också lättare för dig att flytta ditt arbete om änden i huvudkodförrådet har rört sig under tiden.
Om du till exempel vill skicka in en andra funktionsgren till projektet, fortsätt inte att arbeta i den funktionsgren du nyss skickade upp – börja i stället om från kodförrådets huvudgren:
$ git checkout -b featureB origin/master
... work ...
$ git commit
$ git push myfork featureB
$ git request-pull origin/master myfork
... email generated request pull to maintainer ...
$ git fetch origin
Nu är varje funktion isolerad i ett eget fack – som en kö av ändringspatchar – som du kan skriva om, ombasera och ändra utan att funktionerna påverkar eller blir beroende av varandra:
featureB
Om projektets förvaltare har dragit in andra ändringspatchar innan de testar din första gren kan den inte sammanfogas automatiskt.
I det här fallet kan du ombasera den grenen till toppen av origin/master, lösa eventuella konflikter och skicka din version igen:
$ git checkout featureA
$ git rebase origin/master
$ git push -f myfork featureA
Det här skriver om historiken enligt Incheckningshistorik efter avslutat arbete med featureA.
featureA
Eftersom du flyttade grenen behöver du ange -f så att du kan ersätta serverns featureA-gren med en annan incheckning.
Ett alternativ är att skicka det nya arbetet till en annan gren på servern (till exempel featureAv2).
Vi tittar på ytterligare ett alternativ: förvaltarna har tittat på ändringarna i din andra gren och gillar dem mest, men vill att du gör en justering.
Du använder då möjligheten att flytta avgreningens bas från featureA till huvudgrenen.
Du kan göra detta genom att skapa en ny gren från origin/master, sammanfoga featureB där, lösa konflikter, göra justeringen och skicka det som en ny gren:
$ git checkout -b featureBv2 origin/master
$ git merge --squash featureB
... change implementation ...
$ git commit
$ git push myfork featureBv2
Flaggan --squash komprimerar alla incheckningar på grenen som ska sammanfogas till en enda ändring, vilket ger samma status i kodförrådet som vid en sammanslagning.
Det innebär att dina framtida incheckningar bara kommer att ha en förälder och ger dig möjlighet att dra in alla ändringar från en annan gren och göra fler ändringar innan den nya incheckningen skapas.
Ibland kan det vara användbart att använda --no-commit för att fördröja incheckningen vid en sammanslagning.
När detta är klart kan du meddela förvaltaren att ändringarna finns i featureBv2.
featureBv2
Öppet, större projekt via e-post
Många projekt har egna rutiner för att ta emot ändringspatchar – du behöver kontrollera de regler som gäller för varje projekt, eftersom de skiljer sig åt. Eftersom flera äldre och större projekt bara accepterar ändringspatchar via e-postlistor går vi igenom ett exempel på hur det går till.
Arbetsflödet liknar det i föregående exempel – du skapar funktionsgrenar och arbetar där. Den stora skillnaden är att du inte kan skicka dina incheckningar till ett fjärrkodförråd. I stället skickar du varje incheckning via e-post till en e-postlista för utvecklare.
$ git checkout -b topicA
... work ...
$ git commit
... work ...
$ git commit
Nu har du två incheckningar som du vill skicka till e-postlistan.
För att generera mbox-formaterade filer som du kan skicka via e-post använder du git format-patch – det gör varje incheckning till ett e-postmeddelande med första raden i incheckningsmeddelandet som ämne och resten av meddelandet plus ändringspatchen som innehåll.
Det fina är att när en ändringspatch från ett e-postmeddelande genererat med format-patch appliceras bevaras incheckningsinformationen korrekt.
$ git format-patch -M origin/master
0001-add-limit-to-log-function.patch
0002-increase-log-output-to-30-from-25.patch
format-patch skriver ut namnen på ändringspatchfilerna som skapas.
Flaggan -M talar om för Git att leta efter omdöpta filer.
Filerna kommer att se ut så här:
$ cat 0001-add-limit-to-log-function.patch
From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
From: Jessica Smith <jessica@example.com>
Date: Sun, 6 Apr 2008 10:17:23 -0700
Subject: [PATCH 1/2] Add limit to log function
Limit log functionality to the first 20
---
lib/simplegit.rb | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index 76f47bc..f9815f1 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -14,7 +14,7 @@ class SimpleGit
end
def log(treeish = 'master')
- command("git log #{treeish}")
+ command("git log -n 20 #{treeish}")
end
def ls_tree(treeish = 'master')
--
2.1.0
Du kan också redigera ändringspatchfilerna för att lägga till mer information till e-postlistan som du inte vill ska hamna i incheckningsmeddelandet.
Om du lägger till text mellan raden --- och början av ändringspatchen (inleds med diff --git) kan utvecklarna läsa meddelandet, men det ignoreras när ändringspatchen appliceras.
Det är en bra plats att förklara varför du gjort ändringarna eller ge testinstruktioner.
För att skicka ändringspatchfilen till e-postlistan kan du antingen klistra in innehållet i ditt e-postprogram eller skicka det via kommandoraden.
Att klistra in texten orsakar ofta formateringsproblem, särskilt med "smartare" klienter som inte bevarar radbrytningar och mellanslag korrekt.
Som tur är har Git ett verktyg som hjälper dig att skicka korrekt formaterade ändringspatchar via IMAP.
Vi visar hur du skickar en ändringspatch via Gmail, som råkar vara den klient vi känner bäst.
Du kan läsa detaljerade instruktioner för många e‑postklienter i slutet av filen Documentation/SubmittingPatches i Gits källkod.
Först behöver du sätta upp IMAP-delen i din ~/.gitconfig.
Du kan sätta varje värde separat med git config, eller lägga till dem manuellt.
I slutänden ska din konfiguration se ut ungefär så här:
[imap]
folder = "[Gmail]/Drafts"
host = imaps://imap.gmail.com
user = user@gmail.com
pass = YX]8g76G_2^sFbd
port = 993
sslverify = false
Om din IMAP-server inte använder SSL är de två sista raderna troligen onödiga och värdet för host blir imap:// i stället för imaps://.
När det är inställt kan du använda git imap-send för att lägga ändringspatchserien i utkastmappen på den angivna IMAP-servern:
$ cat *.patch | git imap-send
Resolving imap.gmail.com... ok
Connecting to [74.125.142.109]:993... ok
Logging in...
sending 2 messages
100% (2/2) done
Nu borde du kunna gå till din utkastmapp, ändra Till-fältet till e-postlistan du ska skicka ändringspatchen till, lägga till eventuella kopior och skicka iväg den.
Du kan också skicka ändringspatcharna via en SMTP-server.
Precis som tidigare kan du sätta varje värde separat med git config eller lägga till dem manuellt i ~/.gitconfig:
[sendemail]
smtpencryption = tls
smtpserver = smtp.gmail.com
smtpuser = user@gmail.com
smtpserverport = 587
När det är inställt kan du använda git send-email för att skicka ändringspatcharna:
$ git send-email *.patch
0001-add-limit-to-log-function.patch
0002-increase-log-output-to-30-from-25.patch
Who should the emails appear to be from? [Jessica Smith <jessica@example.com>]
Emails will be sent from: Jessica Smith <jessica@example.com>
Who should the emails be sent to? jessica@example.com
Message-ID to be used as In-Reply-To for the first email? y
Git kommer att ställa en rad frågor om hur du vill att e‑posten ska se ut för varje skickad ändringspatch. De kommer att se ut ungefär så här:
(mbox) Adding cc: Jessica Smith <jessica@example.com> from
\line 'From: Jessica Smith <jessica@example.com>'
OK. Log says:
Sendmail: /usr/sbin/sendmail -i jessica@example.com
From: Jessica Smith <jessica@example.com>
To: jessica@example.com
Subject: [PATCH 1/2] Add limit to log function
Date: Sat, 30 May 2009 13:29:15 -0700
Message-Id: <1243715356-61726-1-git-send-email-jessica@example.com>
X-Mailer: git-send-email 1.6.2.rc1.20.g8c5b.dirty
In-Reply-To: <y>
References: <y>
Result: OK
References: <y>
Result: OK
Sammanfattning
I den här delen har vi gått igenom en mängd olika arbetsflöden för olika slags Git‑projekt som du troligen kommer att stöta på, och introducerat verktyg som hjälper dig att hantera processerna. I nästa del får du lära dig hur du hanterar den andra sidan av myntet: att förvalta ett Git‑projekt. Du får lära dig att vara en välvillig diktator eller integrationsansvarig.