Git
Chapters ▾ 2nd Edition

3.1 Veje Git - Veje na kratko

Skoraj vsak VCS ima neko obliko podpore razvejanja. Razvejanje pomeni, da se odmaknete od glavne razvojne linije in nadaljujete delo brez vpletanja v to glavno linijo. V mnogih orodjih VCS je to nekoliko drag postopek, ki od vas pogosto zahteva, da izdelate novo kopijo svojega direktorija izvorne kode, kar lahko traja dolgo časa za večje projekte.

Nekateri se sklicujejo na Gitov model razvejanja kot na njegovo »najboljšo značilnost« in zagotovo postavi Git stran od preostale skupnosti VCS. Zakaj je tako poseben? Način razvejanja v Gitu je izredno lahek, kar omogoča skoraj trenutne operacije razvejanja in hitro preklapljanje med vejami naprej in nazaj. V primerjavi z mnogimi ostalimi VCS-ji, Git spodbuja poteke dela, ki pogosto ustvarijo in združijo veje, celo večkrat na dan. Razumevanje in osvojitev te lastnosti vam da zmogljivo in unikatno orodje ter lahko v celoti spremeni način vašega razvoja.

Veje na kratko

Za resnično razumevanje, na kakšen način Git dela razvejanje, se moramo vrniti korak nazaj in raziskati, kako Git shranjuje svoje podatke.

Kakor se morda spomnite iz Kaj je Git?, Git ne shranjuje podatkov kot serije skupkov sprememb ali razlik, vendar namesto tega kot serije posnetkov.

Ko naredite potrditev, Git shrani objekt potrditve, ki vsebuje kazalec k posnetku vsebine, ki ste jo dali v področje priprave. Ta objekt vsebuje tudi avtorjevo ime in e-pošto, sporočilo, ki ste ga vpisali, in kazalce k potrditvi ali potrditvam, ki so neposredno prišle pred to potrditvijo (njeno nadrejeno ali nadrejene): brez nadrejenih za začetno potrditev, ena nadrejena za običajno potrditev in več nadrejenih za potrditev, ki je rezultat združevanja dveh ali več vej.

Da to vizualiziramo, predpostavimo, da imate direktorij, ki vsebuje tri datoteke in vse daste v področje priprave in nato potrdite. Dajanje datotek v področje priprave izračuna kontrolno vsoto za vsako (zgoščena vrednost SHA-1, ki smo jo omenili v Kaj je Git?), shrani to različico datoteke v repozitorij Git (Git se sklicuje nanje kot blob) in doda to kontrolno vsoto v področje priprave:

$ git add README test.rb LICENSE
$ git commit -m 'Initial commit'

Ko ustvarite potrditev s pogonom git commit, Git preveri kontrolne vsote za vsak poddirektorij (v tem primeru samo vrhnji direktorij projekta) in jih shrani kot drevesni objekt v repozitorij Git. Git nato ustvari objekt potrditve, ki ima metapodatke in kazalec na vrhnje drevo projekta, da lahko ponovno ustvari posnetek, ko je treba.

Vaš repozitorij Git sedaj vsebuje pet objektov: tri blobe (vsak predstavlja vsebino ene izmed treh datotek), eno drevo, ki izpisuje vsebino direktorija in določa, katera imena datotek so shranjena kot blobi, in eno potrditev s kazalcem na to vrhnje drevo ter vse metapodatke potrditve.

Potrditev in njeno drevo
Slika 9. Potrditev in njeno drevo

Če naredite nekaj sprememb in nato ponovno potrdite, bo naslednja potrditev shranila kazalec k potrditvi, ki je prišla takoj pred tem.

Potrditve in njihove nadrejene
Slika 10. Potrditve in njihove nadrejene

Veja v Gitu je enostavno lahek prenosni kazalec k eni od teh potrditev. Privzeto ime veje v Gitu je master. Ko začnete delati potrditve, imate dano vejo master, ki kaže na zadnjo potrditev, ki ste jo naredili. Vsakič, ko potrdite, se kazalec veje master avtomatsko premakne naprej.

Opomba

Veja »master« v Gitu ni posebna veja. Je točno taka kot katerakoli druga veja. Edini razlog, da ima skoraj vsak repozitorij eno, je, da jo ukaz git init privzeto ustvari in večina ljudi se je ne trudi spremeniti.

Veja in njena zgodovina potrditev
Slika 11. Veja in njena zgodovina potrditev

Ustvarjanje nove veje

Kaj se zgodi, ko ustvarite novo vejo? No, to naredi za vas nov kazalec, ki se premika okoli. Recimo, da želite ustvariti novo vejo imenovano testing. To naredite z ukazom git branch:

$ git branch testing

To ustvari nov kazalec na isto potrditev, na kateri ste trenutno.

Dve veji, ki kažeta na isto serijo potrditev
Slika 12. Dve veji, ki kažeta na isto serijo potrditev

Kako Git ve, na kateri veji ste trenutno? Ima poseben kazalec imenovan HEAD. Bodite pozorni, saj je to precej drugačno od zasnove HEAD v drugih VCS-jih, ki ste ga morda vajeni, kot sta Subversion ali CVS. V Gitu je to kazalec na lokalno vejo, kjer ste trenutno. V tem primeru ste še vedno na master. Ukaz git branch je samo ustvaril novo vejo, ni pa tudi preklopil na to vejo.

HEAD, ki kaže na vejo
Slika 13. HEAD, ki kaže na vejo

To lahko enostavno pogledate, da poženete ukaz git log, ki vam prikaže, kam kazalci veje kažejo. Ta možnost se imenuje --decorate.

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

Vidite lahko veji master in testing, ki sta ravno tam zraven potrditve f30ab.

Preklapljanje med vejami

Da preklopite na obstoječo vejo, poženete ukaz git checkout. Preklopimo na novo vejo testing:

$ git checkout testing

To prestavi HEAD, da kaže na vejo testing.

HEAD kaže na trenutno vejo
Slika 14. HEAD kaže na trenutno vejo

Kaj je pomembnost tega? Torej naredimo drugo potrditev:

$ vim test.rb
$ git commit -a -m 'Make a change'
Veja HEAD se premakne naprej, ko je narejena potrditev
Slika 15. Veja HEAD se premakne naprej, ko je narejena potrditev

To je zanimivo, ker se je sedaj vaša veja testing premaknila naprej, vendar vaša veja master še vedno kaže na potrditev, kjer ste bili, ko ste pognali git checkout, da ste preklopili veje. Preklopimo nazaj na vejo master:

$ git checkout master
Opomba
git log ne prikaže vsakič vseh vej

Če bi sedaj pognali git log, bi se morda spraševali, kam je šla veja testing, ki ste jo pravkar ustvarili, saj je ne bi bilo videti v izpisu.

Veja ni izginila; Git preprosto ne ve, da vas ta veja zanima, in poskuša prikazati tisto, kar misli, da vas zanima. Drugače povedano, privzeto bo git log prikazal zgodovino sprememb pod vejo, ki jo imate trenutno izvlečeno.

Da bi prikazali zgodovino sprememb za želeno vejo, jo morate izrecno določiti: git log testing. Za prikaz vseh vej dodajte --all ukazu git log.

HEAD se premakne, ko izvlečete
Slika 16. HEAD se premakne, ko izvlečete

Ta ukaz je naredil dve stvari. Premaknil je kazalec HEAD nazaj na točko veje master in povrnil datoteke v vašem delovnem direktoriju nazaj na posnetek, kamor master kaže. To tudi pomeni, da se bodo spremembe, ki jih delate od te točke naprej, razlikovale od starejše različice projekta. V osnovi presname nazaj delo, ki ste ga naredili na vaši veji testing, tako da lahko greste v drugačno smer.

Opomba
Preklapljanje vej spremeni datoteke v vašem delovnem direktoriju

Pomembno je opozoriti, da ko v Gitu preklopite veje, se datoteke v vašem delovnem direktoriju spremenijo. Če ste preklopili na starejšo vejo, bo vaš delovni direktorij prestavljen nazaj, da je videti tako, kot je prejšnjič, ko ste naredili potrditev na tisti veji. Če Git tega ne more narediti gladko, vam sploh ne bo dovolil preklopiti.

Naredimo nekaj sprememb in ponovno potrdimo:

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

Sedaj se je zgodovina vašega projekta spremenila (glejte sliko Različna zgodovina). Ustvarili in preklopili ste na vejo, naredili nekaj dela na njej in nato preklopili nazaj na svojo glavno vejo ter naredili drugo delo. Obe od teh sprememb sta izolirani v ločenih vejah: lahko preklopite nazaj in naprej med vejama in ju združite skupaj, ko ste pripravljeni. In vse to ste naredili z enostavnimi ukazi branch, checkout in commit.

Različna zgodovina
Slika 17. Različna zgodovina

To lahko enostavno pogledate tudi z ukazom git log. Če poženete git log --oneline --decorate --graph --all, bo izpisal zgodovino vaših potrditev, prikazal, kje so kazalci vej in kako se je vaša zgodovina spremenila.

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

Ker je veja v Gitu dejansko enostavna datoteka, ki vsebuje 40 znakovno kontrolno vsoto SHA-1 potrditve, kamor kaže, so veje ugodne za izdelavo in uničenje. Ustvarjanje nove veje je hitro in enostavno kakor napisati 41 bajtov v datoteko (40 znakov in nova vrstica).

To je v močnem nasprotju z načinom večine vej starejših orodij VCS, ki vključujejo kopiranje vseh datotek projekta v drug direktorij. To lahko vzame nekaj sekund ali celo minut, odvisno od velikosti projekta, kjer pa je proces v Gitu vedno takojšnji. Tudi ker snemamo nadrejene, ko potrjujemo, da najdemo ustrezno združevalno osnovo, saj je združevanje za nas avtomatično izvedeno in ga je v splošnem zelo enostavno narediti. Te lastnosti pomagajo spodbujati razvijalce, da pogostokrat ustvarijo in uporabijo veje.

Poglejmo, zakaj bi to morali tako narediti.

Opomba
Ustvarjanje nove veje in istočasno preklapljanje nanjo

Običajno je narediti novo vejo in istočasno želeti preklopiti nanjo — to se lahko naredi v eni operaciji z git checkout -b <newbranchname>.

Opomba

Od različice Git 2.23 naprej lahko uporabite git switch namesto git checkout, da:

  • Preklopite na obstoječo vejo: git switch testing-branch

  • Ustvarite novo vejo in nanjo preklopite: git switch -c new-branch. Zastavica -c pomeni »ustvarjanje« (angl. create), lahko pa uporabite tudi polno ime zastavice: --create.

  • Se vrnete na vašo prejšnjo izvlečeno vejo: git switch -.

scroll-to-top