Git
Chapters ▾ 2nd Edition

5.3 Distribuerade Git - Underhålla ett projekt

Underhålla ett projekt

Förutom att veta hur du bidrar effektivt till ett projekt, behöver du troligen kunskap om hur man underhåller ett. Det kan innebära att acceptera och tillämpa patcher som genererats via format-patch och skickats till dig via mejl, eller att integrera ändringar i fjärrgrenar. Oavsett om du underhåller ett eget arkiv eller vill hjälpa till med att godkänna patcher, behöver du veta hur man accepterar bidrag på ett strukturerat sätt, dels för att underlätta för bidragslämnare och dels för att underhållet ska bli hållbart för dig över tid.

Arbeta i ämnesgrenar

När det gäller att integrera nytt arbete är det generellt en bra idé att prova hur den fungerar i en ämnesgren — det vill säga en tillfällig gren som är specifikt skapad för att prova det nya arbetet. Det gör det enkelt att justera patcherna individuellt och kunna lämna dem som inte fungerar tills bidragslämnaren har tid att återkomma med förbättringar. Om du skapar ett grennamn baserat på temat för den patch du testar, till exempel ruby_client eller liknande, kommer du enkelt påmind om syftet med grenen om du måste lämna den och komma tillbaka senare. Underhållarna av Git anger en namnrymd för dessa grenar också — till exempel sc/ruby_client, där prefixet sc är förkortningen för personen som bidrog med arbetet. Som du säkert kommer ihåg kan du skapa grenen från din master-gren på följande sätt:

$ git branch sc/ruby_client master

Vill du byta till den direkt använder du istället checkout -b:

$ git checkout -b sc/ruby_client master

Nu är du redo att lägga till det bidragande arbetet när du har bestämt dig för om du vill applicera förslaget i någon av dina långlivade grenar eller inte

Arbeta via mejl

Om du tar emot patcher som ska integreras i ditt projekt via mejl, behöver du först du applicera patchen i din ämnesgren för att kunna granska den. Det finns två sätt att applicera en mejlad patch: med git apply eller med git am.

Applicera en mejlad patch med apply

Om du har fått patchen av någon som genererade den med git diff eller någon variant av Unix diff-kommandot (rekommenderas inte; se mer i nästa avsnitt), kan du applicera den med git apply. Om vi utgår från att du sparade patchen på /tmp/patch-ruby-client.patch, ser det ut så här:

$ git apply /tmp/patch-ruby-client.patch

Kommandot ändrar filerna i ditt lokala arkiv. Det är nästan identiskt som att köra patch -p1 för att applicera patchen, men det accepterar inte lika luddiga matchningar som patch. Det hanterar också filer som läggs till, tas bort och döps om om de beskrivs i git diff-formatet, vilket patch inte gör. Slutligen är git apply en “applicera allt eller avbryt allt”-modell, där allt eller inget appliceras. patch kan å andra sidan applicera delar av patchfiler, men det kan lämna ditt lokala arkiv i ett lite märkligt tillstånd. Övergripande sett är git apply ett mer konservativt kommando än patch. Det kommer inte att göra en inceckning åt dig — när du har kört kommandot behöver du köa och checka in ändringarna manuellt.

git apply kan också användas för att se om en patch kan läggas till utan konflikter innan du försöker applicera den — kör git apply --check följt av patchen-filen:

$ git apply --check 0001-seeing-if-this-helps-the-gem.patch
error: patch misslyckades: ticgit.gemspec:1
error: ticgit.gemspec: patchen kan inte tillämpas

Om det inte finns någon utdata kan patchen integreras utan problem. Detta kommando avslutar med ett nollskilt tal om kontrollen misslyckas, så det kan användas i skript med om du vill.

Applicera en mejlad patch med am

Om bidragslämnaren är en van Git-användare som använde kommandot format-patch för att generera sin patch, blir ditt jobb genast enklare. Patchen innehåller då även författarinformation och ett incheckningsmeddelande. Om du har möjlighet, uppmuntra dina bidragslämnare att använda format-patch istället för diff för att generera patchar till ditt projekt. git apply borde bara användas för patchar till legacy projekt.

För att applicera en patch som genererats av format-patch använder du git am (kommandot heter am eftersom det används för att "applicera en serie patchar från en mejlbox"). Tekniskt sett är git am byggt för att läsa en mbox-fil, som är ett enkelt, textbaserat format för att lagra ett eller flera e-postmeddelanden i en textfil. Det ser ut så här:

Från 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
Från: Jessica Smith <jessica@example.com>
Datum: Sun, 6 Apr 2008 10:17:23 -0700
Ämne: [PATCH 1/2] add limit to log function

Limit log functionality to the first 20

Det här är början på utdata från git format-patch-kommandot som du såg i föregående avsnitt; det är också ett giltigt mbox-e-postformat. Om någon har mejlat patchen till dig på rätt sätt med git send-email och du laddar ner den i mbox-format, kan du peka git am till mbox-filen för att den ska börja applicera alla patchar den ser. Om du använder en mejlklient som kan spara flera mejl i mbox-format, kan hela patchserier sparas i en fil och sen kan du köra git am för att applicera dem en i sänder.

Om någon däremot laddade upp en patchfil som genererats via git format-patch till ett ärendehanteringssystem eller liknande, kan du spara filen lokalt och sedan köra git am för att applicera den:

$ git am 0001-limit-log-function.patch
Applicerar: add limit to log function

Den applicerades utan konflikt och skapade automatiskt en ny incheckning åt dig. Informationen om författaren tas från mejlets Från- och Datum-rubriker, meddelandet i incheckningen tas från Ämne och brödtexten (innan patchen) i mejlet. Om den här patchen applicerades från mbox-exemplet ovan, skulle den genererade incheckningen se ut ungefär så här:

$ git log --pretty=fuller -1
commit 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
Författare:     Jessica Smith <jessica@example.com>
Författardatum: Sun Apr 6 10:17:23 2008 -0700
Incheckning:     Scott Chacon <schacon@gmail.com>
Inchdeckningsdatum: Thu Apr 9 09:19:06 2009 -0700

   add limit to log function

   Limit log functionality to the first 20

Incheckningsinformationen anger vem som applicerade patchen och vid vilken tidpunkt. Författarinformation anger vem som skapade den och när.

Det är inte omöjligt att patchen inte kan appliceras på grund av konflikter. Kanske har din huvudgren divergerat för långt från den gren patchen byggdes från, eller så förgrenades den från en patch som du inte har applicerat än. git am-processen kommer då att misslyckas och du blir tillfrågad om hur du vill lösa konflikten:

$ git am 0001-seeing-if-this-helps-the-gem.patch
Tillämpar: seeing if this helps the gem
error: patch misslyckades: ticgit.gemspec:1
error: ticgit.gemspec: patchen kan inte tillämpas
Patchen misslyckades på 0001.
När du har löst problemet, kör "git am --resolved".
Om du hellre vill hoppa över patchen, kör "git am --skip" istället.
För att återgå till ursprunglig gren och sluta patcha, kör "git am --abort".

Det här kommandot anger i vilka berörda filer det finns konflikter, precis som vid en sammanslagning eller ombasering. Du löser det här problemet på ungefär samma sätt — redigerar filen för att lösa konflikten, köar den nya filen och kör sedan git am --resolved för att fortsätta till nästa patch:

$ (fix the file)
$ git add ticgit.gemspec
$ git am --resolved
Tillämpar: seeing if this helps the gem

Om du vill att Git ska försöka göra en lite mer intelligent operation för att lösa konflikten kan du lägga till en -3-flagga. Git försöker då att göra en trefältsfusion. Det är inte förvalt eftersom det inte fungerar om den incheckning som patchen förgrenades ifrån inte finns i ditt arkiv. Om patchen däremot förgrenades från en offentlig incheckning är -3-flaggan generellt mycket smartare för att applicera en patch med konflikter:

$ git am -3 0001-seeing-if-this-helps-the-gem.patch
Tillämpar: seeing if this helps the gem
error: patch misslyckades: ticgit.gemspec:1
error: ticgit.gemspec: patchen kan inte tillämpas
Använder indexinfo för att återskapa ett basträd...
Faller tillbaka på att patcha grundversionen och trevägssammanslagning...
Inga ändringar -- Patchen har redan tillämpats.

Utan -3-flaggan skulle patchen i det här fallet ha betraktats som konfliktfylld. Med -3-flaggan appliceras den utan problem.

Om du applicerar ett helt gäng patcher från en mbox kan du också köra am-kommandot i interaktivt läge, vilket stannar processen vid varje patch för att fråga om du vill applicera den:

$ git am -3 -i mbox
Incheckningskroppen är:
--------------------------
seeing if this helps the gem
--------------------------
Tillämpa? [Y]=ja/[N]=nej/[E]=redigera/[V]=visa patch/[A]=godta alla:

Det här är användbart om du har många patcher för att kunna se dem först om du inte skulle komma ihåg vad någon handlar om, eller hoppa över någon som du redan har lagt till.

När alla patcher har lagts till och checkats in i din gren behöver du bestämma om och hur du ska integrera dem i en långlivad gren.

Checka ut fjärrgrenar

Om ditt bidrag kom från en Git-användare som har checkat ut sin egen gren, skickat ett antal ändringar till den och sedan skickat URL:en till sitt repo och namnet på den grenen som ändringarna finns i till dig, kan du lägga till den som en fjärrgren och göra sammanslagning lokalt.

Om Jessika till exempel skickar ett mejl och skriver att hon har en bra ny funktion i ruby-client-grenen i sitt arkiv, kan du testa den genom att lägga till den som fjärrgren och checka ut den lokalt:

$ git remote add jessica git://github.com/jessica/myproject.git
$ git fetch jessica
$ git checkout -b rubyclient jessica/ruby-client

Om hon mejlar dig igen med en annan gren som har en annan bra funktion kan du direkt köra fetch och checkout eftersom du redan har ställt in fjärrgrenen.

Det här är mest användbart om du arbetar regelbundet med en person. Om någon bara bidrar med en patch lite då och då är det mindre tidskrävande att acceptera den via e-post än att kräva att alla kör sina egna servrar och ständigt lägga till och ta bort fjärrgrenar för att få några patcher. Du kommer sannolikt inte heller att vilja ha hundratals fjärrgrenar, där de flesta är från någon som bara bidrar med en patch eller två. Hur som helst, skript och hostade tjänster kan göra det enklare — det beror till stor del på hur du och dina bidragslämnare utvecklar.

Den andra fördelen med den här metoden är att du behåller historiken för incheckningarna. Även om du kanske har sammanslagningskonflikter, så vet du var i historiken deras arbete är baserat; en korrekt trefältsfusion är standard istället för att behöva ange en -3 och hoppas att patchen genererades från en offentlig incheckning som du har tillgång till.

Om du inte samarbetar kontinuerligt med en person men ändå vill dra in kod från dem på det här sättet kan du ange URL:en till fjärrarkivet när du kör git pull. Det gör en enstaka hämtning från ett fjärrarkiv utan att spara URL:en som en fjärreferens:

$ git pull https://github.com/onetimeguy/project
Från https://github.com/onetimeguy/project
 * branch            HEAD       -> FETCH_HEAD
Sammanslagning genomförd med strategi 'recursive'.

Avgöra vad som ska integreras

Nu har du en ämnesgren som innehåller ett bidrag. Du behöver nu bestämma vad du vill göra med den. I det här avsnittet går vi igenom några kommandon som du kan använda för att granska exakt vad som kommer att tillämpas om du sammanfogar den här grenen med din huvudgren.

Det är ofta användbart att få en överblick över alla de incheckningar i den här grenen som inte finns i din huvudgren. Du kan utesluta incheckningar i huvudgrenen genom att lägga till --not-flaggan före grennamnet. Det gör samma sak som kommandot master..contrib som vi använde tidigare. Om din bidragslämnare skickar två patchar, du skapar en gren som heter contrib och applicerar dessa patchar där kan du köra detta:

$ git log contrib --not master
commit 5b6235bd297351589efc4d73316f0a68d484f118
Författare: Scott Chacon <schacon@gmail.com>
Datum:   Fri Oct 24 09:53:59 2008 -0700

    seeing if this helps the gem

commit 7482e0d16d04bea79d0dba8988cc78df655f16a0
Författare: Scott Chacon <schacon@gmail.com>
Datum:   Mon Oct 22 19:38:36 2008 -0700

    updated the gemspec to hopefully work better

För att se vad varje incheckning gör, kom ihåg att du kan ange -p-flaggan till git log. Då läggs diffen till som tillämpandet av en patch ger.

För att se en fullständig diff över vad som skulle hända om du sammanfogade hela ämnesgrenen med en annan gren, kan du behöva använda ett lite märkligt trick för att få korrekta resultat. Du kanske tror att du kan köra detta:

$ git diff master

Det här kommandot ger dig mycket riktigt en diff, men om din master-gren har flyttats framåt sedan du förgrenade ämnesgrenen från den är de något vilseledande. Detta beror på att Git direkt jämför ögonblicksbilder av den sista incheckningen på den ämnesgren du är på och ögonblicksbilden av den senaste incheckningen på master-grenen. Om du, till exempel, har lagt till en rad i en fil på master-grenen, kommer en direkt jämförelse av grenarnas ögonblicksbilder få det att se ut som att ämnesgrenen kommer att ta bort den raden.

Om master-grenen inte har rört sig är det inte ett problem, men har historiken divergerat kommer diffen att se ut som att du lägger till allt nytt i din ämnesgren och tar bort allt unikt för master-grenen.

Vad du verkligen vill se är ändringarna som lagts till i funktionsgrenen — resultatet av de ändringar som bblir om du slår ihop den här grenen med master. Det gör du genom att be Git jämföra den sista incheckningen på din temagren med den första gemensamma föregångaren den har med master-grenen.

Tekniskt sett kan du göra det genom att explicit räkna ut den gemensamma föregångaren och sedan köra diff på den:

$ git merge-base contrib master
36c7dba2c95e6bbb78dfa822519ecfec6e1ca649
$ git diff 36c7db

Eller, mer koncist:

$ git diff $(git merge-base contrib master)

Hur som helst så är ingen av dessa särskilt bekväma, så Git ger en annan förkortning för att göra samma sak: trepunktssyntaxen. I kontexten git diff-kommandot kan du sätta tre punkter efter en annan gren för att göra en diff mellan den sista incheckningen på den gren du är på och dess gemensamma föregångare med en annan gren:

$ git diff master...contrib

Det här kommandot visar dig exakt vad som har lagts till i den här grenen sedan den delade föregångaren med master-grenen. Det är en mycket användbar syntax att lägga på minnet.

Integrera kod från bidragslämnare

När allt arbete i din funktionsgren är redo att slås ihop i din huvudgren är frågan hur du ska göra det. Vidare, vilken övergripande arbetsflöde vill du använda för att underhålla ditt projekt? Du har ett antal metoder att välja mellan, och vi kommer att gå igenom några av dem

Arbetsflöden med sammanslagning

Ett grundläggande arbetsflöde är att helt enkelt slå ihop allt arbete direkt i din master-gren. I det här scenariot har du en master-gren som innehåller stabil kod. När du har arbete i en funktionsgren som du tror att du har slutfört, eller arbete som någon annan har bidragit med och du har verifierat, slår du ihop det i din master-gren, tar bort den just sammanfogade temagrenen och upprepar.

Om vi har ett arkiv med arbete i två grenar som heter ruby_client och php_client som ser ut som Historik med flera funktionsgrenar, och vi slår ihop ruby_client följt av php_client, kommer din historik att se ut som Efter en sammanslagning med en funktionsgren..

Historik med flera funktionsgrenar.
Figur 73. Historik med flera funktionsgrenar
Efter en sammanslagning med en funktionsgren.
Figur 74. Efter en sammanslagning med en funktionsgren.

Det här är förmodligen det enklaste arbetsflödet, men det kan bli problematiskt om du arbetar med större eller mer stabila projekt där du vill vara riktigt försiktig med vad du introducerar.

Om du har ett viktigare projekt kanske du vill använda en tvåfas-sammanslagningcykel. I det scenariot har du två långlivade grenar, master och develop, där du bestämmer att master uppdateras endast när en mycket stabil version skapas och all ny kod integreras i develop-grenen. Du skickar regelbundet båda dessa grenar till det publika arkivet. Varje gång du har en ny funktionsgren att slå ihop (Före en sammanslagning av en funktionsgren.), slår du ihop den i develop (Efter en sammanslagning av en funktionsgren.); sedan, när du taggar en version, snabbspolar du master till där develop-grenen är stabil (Efter en ny version.).

Före en sammanslagning av en funktionsgren.
Figur 75. Före en sammanslagning av en funktionsgren.
Efter en sammanslagning av en funktionsgren.
Figur 76. Efter en sammanslagning av en funktionsgren.
Efter en ny version.
Figur 77. Efter en ny version.

På det här sättet, när folk klonar ditt projekts arkiv, kan de antingen kolla ut master för att bygga den senaste stabila versionen och enkelt hålla sig uppdaterade på den, eller kolla ut develop, som är den mer skärpta innehållet. Du kan också utöka det här konceptet genom att ha en integrate-gren där allt arbete sammanfogas. När kodbasen på den grenen är stabil och passerar tester, slår du ihop den i en develop-gren; och när den har visat sig vara stabil under en tid, snabbspolar du din master-gren.

Arbetsflöde med stora sammanslagningar

Git-projektet har fyra långlivade grenar: master, next och pu (proposed updates) för nytt arbete, och maint för underhållsbackportar. När nytt arbete introduceras av bidragslämnare samlas det i temagrenar i förvaltarens arkiv på ett sätt som liknar det som har beskrivits (se Hantera en komplex serie med parallella ämnesgrenar.). Vid det här laget utvärderas temana för att avgöra om de är säkra och redo för användning eller om de behöver mer arbete. Om de är säkra slås de ihop i next, och den grenen pushas upp så att alla kan prova temana integrerade tillsammans.

Hantera en komplex serie med parallella ämnesgrenar.
Figur 78. Hantera en komplex serie med parallella ämnesgrenar.

Om det behövs mer arbete på en temagren slås den ihop med pu istället. När det har bestämts att de är helt stabila slås de ihop med master-grenen. next- och pu-grenarna byggs sedan om från master. Det här innebär att master nästan alltid rör sig framåt, next ombaseras ibland, och pu ombaseras ännu oftare:

Slå ihop ämnesgrenar med långlivade integrationsgrenar.
Figur 79. Slå ihop ämnesgrenar med långlivade integrationsgrenar.

När en ämnesgren äntligen har slagits ihop med master-grenen tas den bort från arkivet. Git-projektet hr också en maint-gren som är en gren som är förgrenad från den senaste versionen för att tillhandahålla bakåtkompatibla patchar om en underhållsversion krävs. Så, när du klonar Git-arkivet har du fyra grenar som du kan kolla ut för att utvärdera projektet i olika utvecklingsstadier, beroende på hur nyskapande du vill vara eller hur du vill bidra; och förvaltaren har ett strukturerat arbetsflöde för att hjälpas åt att granska nya bidrag. Git-projektet har ett specialiserat arbetsflöde. För att förstå det bättre kan du läsa mer på Git Maintainer’s guide.

Arbetsflöden med ombasering och plocka russin ur kakan

När du har arbete i en temagren och har bestämt att du vill integrera det, kan du göra det på två sätt: genom att ombasera eller plocka russin ur kakan. Vissa förvaltare föredrar att ombasera eller plocka russin ur kakan för att hålla en mestadels linjär historik. När du har arbete i en temagren och har bestämt att du vill integrera det, flyttar du till den grenen och kör ombasera-kommandot för att bygga om ändringarna på din nuvarande master-gren (eller develop, och så vidare). Om det går bra kan du snabbspola din master-gren. I slutänden får du en linjär projektshistorik.

Ett annat sätt att flytta in arbete från en gren till en annan är att plocka russin ur kakan. Att plocka russin ur kakan i Git är som en ombasering men för en enskild incheckning. Det tar en patch från en incheckning och försöker applicera den på den gren du är på. Detta är användbart om du har ett antal incheckningar på en temagren och du baran vill integrera en av dem, eller om du föredrar att plocka in incheckningarna en och en istället för att göra en ombasering. Om du till exempel har ett projekt som ser ut så här:

Exempel historik före russin plockats ur kakan.
Figur 80. Exempel historik före russin plockats ur kakan.

Om du vill dra in incheckningen e43a6 i din master-gren kan du köra

$ git cherry-pick e43a6
Avslutade en cherry-pick.
[master]: created a0a41a9: "More friendly message when locking the index fails."
 3 filer ändrade, 17 tillagda(+), 3 borttagna(-)

Det här drar in ändringarna i incheckning e43a6 in i din master-gren., men du får ett nytt SHA-1-värde för incheckningen eftersom datumet som den tillämpades är annorlunda. Din historik ser nu ut så här:

Historik efter russinplockning av en inceckning på en funktionsgren.
Figur 81. Historik efter russinplockning av en inceckning på en funktionsgren.

Nu kan du radera din funktionsgren och släppa incheckningarna som du inte vill få in.

Rerere

Om du gör massor av sammanslagningar och ombaseringar, eller om du underhåller en långlivad funktionsgren, har Git en funktion som heter “rerere” som kan vara användbar.

Rerere står för “reuse recorded resolution” — det är ett sätt att förkorta manuell konflikthantering. När rerere är aktiverat kommer Git att behålla en uppsättning före- och efterbilder från lyckade sammanslagningar, och om det märker att det finns en konflikt som ser precis ut som en du redan har löst, kommer Git bara att använda lösningen från förra gången, utan att störa dig med den. Rerere stands for “reuse recorded resolution” — it’s a way of shortcutting manual conflict resolution. When rerere is enabled, Git will keep a set of pre- and post-images from successful merges, and if it notices that there’s a conflict that looks exactly like one you’ve already fixed, it’ll just use the fix from last time, without bothering you with it.

Funktionen har två delar: en konfigurationsinställning och ett kommando. Konfigurationsinställningen är rerere.enabled, och det är tillräckligt användbart för att lägga i din globala konfiguration:

$ git config --global rerere.enabled true

När du än gör en sammanslagning som löser konflikter, kommer lösningen nu att sparas i cachen om den skulle behövas i framtiden.

Om du behöver kan du interagera med rerere-cachen med hjälp av kommandot git rerere. När det används ensamt, kollar Git sin databas med lösningar och försöker hitta en matchning med eventuella aktuella konflikter och lösa dem (även om det görs automatiskt om rerere.enabled är inställt på true). Det finns också underkommandon för att se vad som kommer att sparas, för att radera specifika lösningar från cachen och för att rensa hela cachen. Vi kommer att gå in på rerere mer i detalj i Rerere.

Versionsmarkeringar

När du har bestämt dig för att släppa en ny version av ditt projekt, vill du förmodligen tilldela en tagg så att du kan återskapa den versionen när som helst framöver. Du kan skapa en ny tagg som diskuterats i Grunder i Git. Om du bestämmer dig för att signera taggen som underhållare ser taggningen ut så här:

$ git tag -s v1.5 -m 'my signed 1.5 tag'
You need a passphrase to unlock the secret key for
user: "Scott Chacon <schacon@gmail.com>"
1024-bit DSA key, ID F721C45A, created 2009-02-09

Om du signerar dina taggar kan du få problem med att distribuera den offentliga PGP-nyckeln som används för att signera dina taggar. Förvaltaren för Git-projektet har löst detta problem genom att inkludera sin offentliga nyckel som en blob i arkivet och sedan lägga till en tagg som pekar direkt på det innehållet. För att göra detta kan du ta reda på vilken nyckel du vill använda genom att köra gpg --list-keys:

$ gpg --list-keys
/Users/schacon/.gnupg/pubring.gpg
---------------------------------
pub   1024D/F721C45A 2009-02-09 [expires: 2010-02-09]
uid                  Scott Chacon <schacon@gmail.com>
sub   2048g/45D02282 2009-02-09 [expires: 2010-02-09]

Du kan då importera nyckeln direkt i Git-databasen genom att exportera den och skicka den genom git hash-object, som skriver en ny blob med de innehållen i Git och ger dig tillbaka SHA-1 för blobben:

$ gpg -a --export F721C45A | git hash-object -w --stdin
659ef797d181633c87ec71ac3f9ba29fe5775b92

Nu när du har innehållet i din nyckel i Git kan du skapa en tagg som pekar direkt på den genom att ange det nya SHA-1-värdet från hash-object:

$ git tag -a maintainer-pgp-pub 659ef797d181633c87ec71ac3f9ba29fe5775b92

Med kommandot git push --tags kan du nu dela taggen maintainer-pgp-pub med alla. Om någon vill verifiera en tagg kan de direkt importera din PGP-nyckel genom att dra ut blobben direkt ur databasen och importera den i GPG:

$ git show maintainer-pgp-pub | gpg --import

De kan också använda den nyckeln för att verifiera alla dina signerade taggar. Om du dessutom inkluderar instruktioner i taggmeddelandet kan körning av git show <tagg> låta dig ge slutanvändaren mer specifika instruktioner om taggverifiering.

Generera versionsnummer

I Git finns det inget inbyggt sätt att generera löpande versionsnummer som v123 eller liknande för varje incheckning. Om du vill ha ett versionnummber som är logiskt för människor för varje incheckning, kan du köra git describe på incheckningen. Till svar genererar Git en sträng som består av namnet på den senaste taggen tidigare än den incheckningen, följt av antalet incheckningar sedan den taggen, följt av en del av SHA-1-värdet för den incheckningen (föregånget av bokstaven g som betyder Git):

$ git describe master
v1.6.2-rc1-20-g8c5b85c

På det här sättet kan du få en sträng som är meningsfull för människor att använda som versionsnummer. Om du bygger Git från källkoden som är klonad från Git-arkivet ger git --version dig något som ser ut så här. Om du beskriver en incheckning som du direkt har taggat ger den dig helt enkelt taggnamnet.

git describe-kommandot kräver annoterade taggar som standard (taggar som skapats med flaggorna -a eller -s); om du vill dra nytta av lättviktiga (icke-annoterade) taggar också, lägg till --tags-flaggan till kommandot. Du kan också använda den här strängen som mål för ett git checkout- eller git show-kommando, även om det förlitar sig på det förkortade SHA-1-värdet i slutet, så det kanske inte är giltigt för evigt. Till exempel hoppade Linux-kärnan nyligen från 8 till 10 tecken för att säkerställa SHA-1-objektens unicitet, så äldre git describe-utdata namn ogiltigförklarades.

Förbereda ett släpp

Nu vill du släppa en ny version. En av de saker du vill göra är att skapa ett arkiv av den senaste ögonblicksbilden av din kod för de arma själar som inte använder Git. Kommandot för att göra detta är git archive:

$ git archive master --prefix='project/' | gzip > `git describe master`.tar.gz
$ ls *.tar.gz
v1.6.2-rc1-20-g8c5b85c.tar.gz

Om någon öppnar det arkivet får de den senaste ögonblicksbilden av ditt projekt i en projektkatalog. Du kan också skapa ett zip-arkiv ungefär på samma sätt men genom att ange --format=zip-flaggan till git archive:

$ git archive master --prefix='project/' --format=zip > `git describe master`.zip

Nu har du en snyggt arkiv och en zipkatalog av ditt projekts släpp som du kan ladda upp till din webbplats eller mejla till folk.

Shortlog

Det är dags att mejla till din mejllista med personer som vill veta vad som händer i ditt projekt. Ett trevligt sätt att snabbt få en slags ändringslogg över vad som har lagts till i ditt projekt sedan ditt senaste släpp eller mejl är att använda kommandot git shortlog. Det sammanfattar alla incheckningar i det intervall du ger det; till exempel ger följande en sammanfattning av alla incheckningar sedan ditt senaste släpp, om ditt senaste släpp hette v1.0.1:

$ git shortlog --no-merges master --not v1.0.1
Chris Wanstrath (6):
      Add support for annotated tags to Grit::Tag
      Add packed-refs annotated tag support.
      Add Grit::Commit#to_patch
      Update version and History.txt
      Remove stray `puts`
      Make ls_tree ignore nils

Tom Preston-Werner (4):
      fix dates in history
      dynamic version method
      Version bump to 1.0.2
      Regenerated gemspec for version 1.0.2

Du får en enhetlig sammanfattning av samtliga incheckningar sedan v1.0.1, grupperade efter författare, som du kan skicka till din mejllista.

scroll-to-top