Git
Chapters ▾ 2nd Edition

3.1 Veje Git - Veje na kratko

Skoraj vsak VCS ima neko obliko podpore vej. Veje pomenijo, da naredite raznolikost iz glavne linije razvoja in nadaljujete delo brez vpletanja s to glavno linijo. V mnogih orodjih VCS, je to nekako drag proces, pogosto zahteva od vas, da izdelate novo kopijo vašega direktorija izvorne kode, ki lahko vzame dalj časa za večje projekte.

Nekateri se sklicujejo na Gitov model razvejanja kot njegovo “ubijalsko lastnost” in zagotovo postavi Git stran od VCS skupnosti. Zakaj je tako posebno? Način Git vej je izredno lahek, operacije vej naredi skoraj takojšnje in preklaplanje nazaj in naprej med vejami je v splošnem tudi tako hitro. Z razliko od ostalih VCS-jev, Git spodbuja potek dela, ki pogosto naredi veje in jih združi, celo večkrat na dan. Razumevanje in osvojitev te lastnosti vam da močno in unikatno orodje in lahko v celoti spremeni način, kako razvijate.

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 Pričetek, Git ne shranjuje podatkov kot serije skupkov sprememb ali razlik, vendar namesto tega kot serije posnetkov.

Ko naredite pošiljanje, Git shrani objekt pošiljanja, ki vsebuje kazalec k posnetku vsebine, ki ste jo dali v vmesno fazo. Ta objekt tudi vsebuje ime avtorja in e-pošto, sporočilo, ki ste jo vpisali in kazalce k pošiljanju ali pa pošlje to, kar je direktno prišlo pred tem pošiljanjem (svoj starš od staršev): nobenih staršev za začetne pošiljanje, en starš za običajno pošiljanje in več staršev za pošiljanje, ki je rezultat združevanja dveh ali več vej.

Da to vizualiziramo, predpostavimo, da imate direktorij, ki vsebuje tri datoteke in vse date v vmesno fazo in pošljete. Dajanje datotek v vmesno fazo preveri vsote vsake (SHA-1 zgoščevanje, ki smo ga omenili v Pričetek) shrani to verzijo datoteke v Git repozitorij (Git se sklicuje nanj kot blob) in doda to preverjeno vsoto v vmesno fazo:

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

Ko ustvarite pošiljanje z pogonom git commit, Git preveri vsote za vsak poddirektorij (v tem primeru samo vrhnji direktorij projekta) in shrani te objekte drevesa v Git repozitorij. Git nato ustvari objekt pošiljanja, ki ima meta podatke in kazalec na vrhnje drevo projekta, da lahko ponovno ustvari posnetek, ko je potrebno.

Vaš repozitorij Git sedaj vsebuje pet objektov: en blob za vsebine vsake od vaših treh datotek, eno drevo, ki izpisuje seznam vsebine direktorija in določa katera imena datotek so shranjena kot blob-i in eno pošiljanje s kazalcem na vrhnje drevo in vse meta podatke pošiljanja.

A commit and its tree.
Figure 9. A commit and its tree

Če naredite nekaj sprememb in nato ponovno pošljete, naslednje pošiljanje shrani kazalec k pošiljanju, ki je prišlo takoj pred tem.

Commits and their parents.
Figure 10. Commits and their parents

Veja v Git-u je enostavno lahek prenosen kazalec k enemu od teh pošiljanj. Privzeto ime veje v Git-u je master. Kot ste začeli delati pošiljanja, imate dano master vejo, ki kaže na zadnje pošiljanje, ki ste ga naredili. Vsakič, ko pošljete, ga premakne naprej avtomatsko.

Note

Veja “master” v Git-u ni posebna veja. Je točno kot katerakoli druga veja. Edini razlog, da ima skoraj vsake repozitorij eno, je, da jo ukaz git init ustvari privzeto in večina ljudi se ne trudi tega spremeniti.

A branch and its commit history.
Figure 11. A branch and its commit history

Ustvarjanje nove veje

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

$ git branch testing

To ustvari nov kazalec na isto pošiljanje, na katerem ste trenutno.

Two branches pointing into the same series of commits.
Figure 12. Two branches pointing into the same series of commits

Kako Git ve, na kateri veji ste trenutno? Ima poseben kazalec imenovan HEAD. Bodite pozorni, da je to precej različno od koncepta HEAD v drugih VCS-jih, ki ste ga morda vajeni, kot sta Subversion ali CVS. V Git-u 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 preklopil na to vejo.

HEAD pointing to a branch.
Figure 13. HEAD pointing to a branch

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

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

Vidite lahko “master” in “testing” veji, ki sta ravno tam zraven pošiljanja f30ab.

Switching Branches

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

$ git checkout testing

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

HEAD points to the current branch.
Figure 14. HEAD points to the current branch

Kaj je pomembnost tega? Torej naredimo drugo pošiljanje:

$ vim test.rb
$ git commit -a -m 'made a change'
The HEAD branch moves forward when a commit is made.
Figure 15. The HEAD branch moves forward when a commit is made

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

$ git checkout master
HEAD moves when you checkout.
Figure 16. HEAD moves when you checkout

Ta ukaz naredi dve stvari. Premaknil je HEAD kazalec nazaj na točko master veje 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 verzije projekta. Pomembno je presneti nazaj delo, ki ste ga naredili na vaši testing veji, ta lahko greste v različno smer.

Note
Switching branches changes files in your working directory

Pomembno je opozoriti, da ko preklopite veje v Git-u, se datoteke v vašem delovnem direktoriju spremenijo. Če ste preklopili na starejšo vejo, bo vaš delovni direktorij prestavljen nazaj, da bo izgledal tako kot je prejšnjič, ko ste poslali na tisti veji. Če Git to ne more narediti čisto, vam ne bo dovolil preklopiti.

Naredimo nekaj sprememb in ponovno pošljimo:

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

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

Divergent history.
Figure 17. Divergent history

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

$ 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

Ker je veja v Git-u dejansko enostavna datoteka, ki vsebuje 40 znakovno SHA-1 preverjeno vsoto pošiljanja, kamor kaže, so veje poceni za izdelati in uničiti. Ustvarjanje nove veje je hitro in enostavno kakor napisati 41 bajtov v datoteko (40 znakov in nova vrstica).

To je v ostrem kontrastu z načinom večine vej starejših VCS orodij, ki vključujejo kopiranje vseh datotek projekta v drug direktorij. To lahko vzame nekaj sekund ali celo minut, odvisno od velikosti projekta, kjer je v Git-u proces vedno takojšnji. Tudi ker snemate starše, ko pošljete, iščete ustrezno združevalno osnovo, saj je združevanje narejeno avtomatično za nas in je v splošnem zelo enostavno narediti. Te lastnosti pomagajo spodbujati razvijalcem ustvariti in uporabiti veje pogostokrat.

Poglejmo zakaj bi to morali tako narediti.