Git 🌙
Chapters â–Ÿ 2nd Edition

3.1 Git förgreningar - Grenar i ett nötskal

NÀstan alla versionshanteringssystem har nÄgon form av stöd för förgreningar. En förgrening innbÀr att du avviker frÄn utvecklingens huvudspÄr och fortsÀtter att arbeta utan att pÄverka huvudspÄret. I mÄnga versionshanteringsverktyg Àr detta Àr ganska dyr process som ofta innebÀr att skapa en ny kopia av kÀllkodsmappen och tar lÄng tid för stora projekt.

En del refererar till Gits förgreningsmodell som dess “mördarfunktion,” och den gör verkligen att Git sticker ut i versionshanteringsvĂ€rlden. Vad Ă€r sĂ„ speciellt? Det sĂ€tt som Git gör grenar pĂ„ Ă€r fantastiskt lĂ€ttviktigt och att skapa nya grenar görs nĂ€st intill ögonblickligen, likasĂ„ att byta mellan olika grenar. Olikt mĂ„nga andra versionshanteringssystem uppmuntrar Git till ett arbetsflöde dĂ€r man ofta förgrenar och slĂ„r ihop dem ofta, Ă€ven flera gĂ„nger dagligen. Att förstĂ„ och behĂ€rska denna teknik ger dig ett kraftfullt och unikt verktyg och kan helt pĂ„vekar hur du vĂ€ljer att utveckla.

Grenar i ett nötskal

För att verligen förstÄ hur Git anvÀnder grenar mÄste vi ta ett steg tillbaka och undersöka hur Git sparar data.

Som du kanske kommer ihÄg frÄn Kom igÄng sÄ sparar Git inte data som en serie Àndringar eller skillnader, utan istÀllet som en serie ögonblicksbilder.

NÀr du skapar en version, skapar Git ett versionsobjekt som innehÄller en pekare till ögonblicksbilden av innehÄllet du förberett för Àndringen. Detta objektet innehÄller författarens namn och e-postadress, meddelandet som angavs, och pekare till den version eller de versioner som var direkt före denna version (dess förÀlder eller förÀldrar): Ina förÀldrar för den första versionen, en förÀlder för en normal version och flera förÀldrar för en version som Àr resultatet efter en sammanslagning mellan tvÄ eller flera grenar.

För att visualisera detta, anta att du har en mapp som innehÄller tre filer. Du preparerar alla och dÀrefter skapar din version. NÀr du preparerar filerna berÀknas en checksumma för varje fil (SHA-1 kontrollsumman som vi nÀmnt tidigare i Kom igÄng), lagrar versionen av filen i Git-förvaret (Git refererar till dem som blobbar), och lÀgger till kontrollsumman till prepareringsytan:

$ git add README test.rb LICENSE
$ git commit -m 'The initial commit of my project'

NÀr du skapar en version genom att köra git commit, berÀknar Git en kontrollsumma för varje underkatalog (i detta fall enbart projektets rotkatalog) och sparar dessa tre objekt i Git-förvar. Git skapar sedan ett versionsobjekt som har metadata och en pekare till rotkatalogens projekttrÀd sÄ att den kan Äterskapa den ögonblicksbilden nÀr sÄ behövs.

Ditt Git-förvar innehÄller nu fem objekt: tre blobbar (varje representerar innehÄllet i en av de tre filerna), ett trÀd som listar innehÄllet i en katalog och specificerar vilka filnamn som finns lagrade som vilka blobbar, och en version med pekaren till det rottrÀdet och versionens metadata.

A commit and its tree.
Figur 9. En version och dess trÀd.

Om du gör nÄgra Àndringar och skapar en ny version, kommer nÀsta version spara en pekare till den version som var omedelbart före denna.

Commits and their parents.
Figur 10. Versioner och deras förÀldrar

En gren i Git Àr bara en enkel flyttbar pekare till nÄgon av dessa versioner. Standardgrenen i Git Àr master. Om du börjar skapa vereionser, sÄ fÄr du en master-gren som pekar pÄ din senast sparade version. Varje gÄng du gör en ny version, sÄ förflyttas master-pekaren med framÄt automatiskt.

Notera

Grenen “master” i Git Ă€r inte speciell. Den Ă€r precis som vilken annan gren som helst. Enda anledningen att nĂ€stan alla förvar har en, Ă€r för att kommandot git init skapar den som standard och de flesta bryr sig inte om att Ă€ndra det.

A branch and its commit history.
Figur 11. En gren och dess versionshistorik.

Skapa en ny gren

Vad hÀnder nÀr du skapar en ny gren? Att göra det skapar en ny pekare som du kan flyutta runt. Anta att du vill skapa en gren som heter testing. Du kan göra detta med kommandot git branch:

$ git branch testing

Detta skapar en ny pekare till samma version som du just nu stÄr pÄ.

Two branches pointing into the same series of commits.
Figur 12. TvÄ grenar pekar pÄ samma serie av versioner

Hur vet Git vilken gren du just nu stĂ„r pĂ„? Den har en speciell pekare som kallas HEAD. Notera att detta Ă€r mycket annorlunda Ă€n konceptet HEAD i andra versionshanteringssystem som du kanske anvĂ€nt, som t.ex. Subversion eller CVS. I Git Ă€r detta en pekare till den lokala gren du just nu stĂ„r pĂ„. I detta fallet Ă€r du fortfarande pĂ„ master. Kommandot git branch skapade bara en ny gren — den bytte inte till den grenen.

HEAD pointing to a branch.
Figur 13. HEAD pekar pÄ en gren

Du kan enkelt se detta genom att köra kommandot git log som visar va grenpekarna pekar pÄ. Denna flagga kallas --decorate.

$ git log --oneline --decorate
f30ab (HEAD -> master, testing) add feature #32 - ability to add new formats to the central interface
34ac2 Fixed bug #1328 - stack overflow under certain conditions
98ca9 The initial commit of my project

Du kan se grenarna “master” och “testing” som Ă€r precis vid versionen f30ab.

Byta grenar

Att byta till en existerande gren görs med kommandot git checkout. LÄt oss byta till den nya grenen testing:

$ git checkout testing

Detta flyttar HEAD till att peka pÄ grenen testing.

HEAD points to the current branch.
Figur 14. HEAD pekar pÄ aktuell gren

Vad Àr vitsen med det? LÄt oss illustrera genom att skapa en ny version:

$ vim test.rb
$ git commit -a -m 'made a change'
The HEAD branch moves forward when a commit is made.
Figur 15. Grenen som HEAD pekar pÄ flyttar fram nÀr en version sparas

Det intressanta Àr att din gren testing har flyttat fram, men din master-gren pekar fortfarande pÄ versionen du var pÄ innan du körde git checkout för att byta gren. LÄt oss gÄ tillbaks till master-grenen:

$ git checkout master
HEAD moves when you checkout.
Figur 16. HEAD flyttar nÀr du gör checkout

Kommandot gjorde tvÄ saker. Den flyttade din HEAD pekare tillaka till grenen master och den ÄterstÀllde filerna i din arbetskopia till ögonblicksbilden som master pekar pÄ. Detta betyder att alla Àndringar frÄn och med nu kommer divergera frÄn en tidigare version av projektet. I praktiken gör den det jobb du gjort i din testing-gren ogjort sÄ att du kan gÄ i en annan riktning.

Notera
Byta grenar Àndrar filer i din arbetskopia

Det Àr viktigt att veta att nÀr du byter gren i Git sÄ Àndras filer i din arbetskopia. Om du byter till en Àldre gren kommer din arbetskopia ÄterstÀllas till att se ut som den gjorde senast du gjorde en version pÄ den grenen. Om Git inte kan göra detta utan att kasta icke-versionshanterat arbete, kommer du inte tillÄtas byta alls.

LÄt oss göra nÄgra Àndringar och spara en till version:

$ vim test.rb
$ git commit -a -m 'made other changes'

Nu har din projekthistorik divergerat (se Divergent historik). Du skapade och bytte till en gren, gjorde lite arbete pÄ den, och sedan bytte du tillbaks till ditt huvudspÄr och gjorde lite annat arbete. BÄda Àndringarna Àr isolerade i olika grenar: du kan byta fram och tillbaka mellan grenarna och slÄ ihop dem nÀr du Àr redo. Allt detta gjorde du med nÄgra enkla kommandon; branch, checkout och commit.

Divergent history.
Figur 17. Divergent historik

Du kan ocksÄ se detta enkelt med kommandot git log. Om du kör git log --oneline --decorate --graph --all sÄ skrivs hela din versionshistorik ut, samt var dina grenar pekar och visar hur din historik har divergerat.

$ git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) made other changes
| * 87ab2 (testing) made a change
|/
* f30ab add feature #32 - ability to add new formats to the
* 34ac2 fixed bug #1328 - stack overflow under certain conditions
* 98ca9 initial commit of my project

Eftersom en gren i Git egentligen Àr en fil som innehÄller den 40 tecken lÄnga SHA-1 kontrollsumman av versionen den pekar pÄ, Àr grenar enkla att skapa och ta bort. Att skapa en ny gren Àr lika enkelt som att skriva 41 byte till en fil (40 tecken och ett nyradstecken).

Detta Àr i skarp kontrast till hur de flesta Àldre versionshanteringssystem fungerar, dÄ förgreningar innefattar att kopiera hela projektets filer till en ny katalog. Detta kan ta flera sekunder eller till och med minuter, beroende pÄ storleken pÄ projektet, men i Git Àr processen alltid momentan. Eftersom vi lagrar informationen om förÀldrarna till en version blir det lÀtt att automatiskt hitta en bra bas för sammanslagning och det Àr ganska lÀtt att genomföra. Detta uppmuntrar utvecklare att skapa och anvÀnda grenar ofta.

LÄt oss undersöka varför vi skall göra pÄ detta viset.

Notera
Skapa en ny gren och byta till den samtidigt

Det hĂ€nder ofta att du vill skapa en ny gren och byta till den omedelbart. — Detta kan göras med en operation genom kommandot git checkout -b <nyttgrennamn>.

scroll-to-top