Git
Chapters ▾ 2nd Edition

3.2 Veje Git - Osnove vej in združevanja

Osnove vej in združevanja

Pojdimo skozi enostaven primer vej in združevanja s potekom dela, ki ga morda uporabljate v resničnem svetu. Sledili boste tem korakom:

  1. Naredite nekaj na spletni strani.

  2. Ustvarite vejo za novo uporabniško zgodbo (angl. user story), na kateri delate.

  3. Naredite nekaj na tej veji.

V tej fazi boste prejeli klic, da je kritična neka druga težava in potrebujete hitri popravek. Naredili boste naslednje:

  1. Preklopite na svojo produkcijsko vejo.

  2. Ustvarite vejo, da dodate hitri popravek.

  3. Ko je testiran, združite vejo hitrega popravka in potisnete v produkcijo.

  4. Preklopite nazaj na svojo prvotno uporabniško zgodbo in nadaljujete delo.

Osnove vej

Za začetek recimo, da delate na svojem projektu in imate že nekaj potrditev na veji master.

Enostavna zgodovina potrditev
Slika 18. Enostavna zgodovina potrditev

Odločili ste se, da boste delali na težavi #53 kateregakoli sistema sledenja težav, ki ga vaše podjetje uporablja. Da ustvarite vejo in istočasno nanjo preklopite, lahko poženete ukaz git checkout s stikalom -b:

$ git checkout -b iss53
Switched to a new branch "iss53"

To je bližnjica za:

$ git branch iss53
$ git checkout iss53
Ustvarjanje novega kazalca na vejo
Slika 19. Ustvarjanje novega kazalca na vejo

Delate na svoji spletni strani in naredite nekaj potrditev. S tem se veja iss53 premakne naprej, ker ste jo izvlekli (to pomeni, da vaš HEAD kaže nanjo):

$ vim index.html
$ git commit -a -m 'Create new footer [issue 53]'
Veja `iss53` se je premaknila naprej z vašim delom
Slika 20. Veja iss53 se je premaknila naprej z vašim delom

Sedaj dobite klic, da je težava s spletno stranjo in jo morate takoj popraviti. Z Gitom vam ni treba postaviti vašega popravka skupaj s spremembami iss53, ki ste jih naredili, in ni vam treba vložiti veliko napora v povračanje teh sprememb, preden lahko delate na nameščanju svojega popravka na to, kar je v produkciji. Vse kar morate narediti, je preklopiti nazaj na vašo vejo master.

Vendar preden to naredite, pomnite, da če ima vaš delovni direktorij ali področje priprave nepotrjene spremembe, ki so v konfliktu z vejo, ki jo izvlečete, vam Git ne bo dovolil preklopiti vej. Ko preklapljate veje, je najbolje imeti čisto delovno stanje. Obstajajo načini, da se temu izognete (v glavnem, shranjevanje na varno in potrjevanje sprememb), kar bomo pokrili kasneje v Shranjevanje na varno (angl. stashing) in čiščenje. Za sedaj predpostavimo, da ste potrdili vse svoje spremembe, tako da lahko preklopite nazaj na vašo vejo master:

$ git checkout master
Switched to branch 'master'

Na tej točki je vaš delovni direktorij projekta točno tak, kakor je bil preden, ste začeli delati na težavi #53 in sedaj se lahko osredotočite na svoj hitri popravek. To je pomembna točka za zapomniti: ko preklapljate veje, Git ponastavi vaš delovni direktorij, da je videti tako, kot je, ko ste zadnjič naredili potrditev na tej veji. Avtomatično doda, odstrani in spremeni datoteke, da zagotovi, da je vaša delovna kopija taka, kot je bila veja na vaši zadnji potrditvi na njej.

Naslednje morate narediti hitri popravek. Ustvarimo vejo hitrega popravka hotfix, na kateri delate, dokler ni končan:

$ git checkout -b hotfix
Switched to a new branch 'hotfix'
$ vim index.html
$ git commit -a -m 'Fix broken email address'
[hotfix 1fb7853] Fix broken email address
 1 file changed, 2 insertions(+)
Veja hitrega popravka osnovana na `master`
Slika 21. Veja hitrega popravka osnovana na master

Poženete lahko svoje teste, zagotovite, da je hitri popravek, kakršen ga želite, in na koncu združite vejo hotfix nazaj v vašo vejo master, da postavite na produkcijo. To naredite z ukazom git merge:

$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

V tej združitvi boste opazili frazo »fast-forward« (hitro previjanje naprej). Ker je potrjevanje C4, kamor kaže veja hotfix, ki ste jo združili, neposredno pred potrditvijo `C2, na kateri ste, Git enostavno premakne kazalec naprej. Povedano drugače, ko poskušate združiti eno potrditev z drugo, ki je lahko dosegljiva s sledenjem zgodovine prve potrditve, Git poenostavi stvari, tako da prestavi kazalec naprej, ker ni nobenega različnega dela za združiti skupaj — to se imenuje »fast-forward«.

Vaša sprememba je sedaj v posnetku potrditve, ki kaže na vejo master, in programski popravek lahko postavite.

Veja `master` je hitro previta naprej na `hotfix`
Slika 22. Veja master je hitro previta naprej na hotfix

Ko je vaš zelo pomemben hitri programski popravek postavljen, ste pripravljeni preklopiti nazaj k delu, ki ste ga delali, preden so vas zmotili. Vendar najprej boste izbrisali vejo hotfix, ker je ne potrebujete več — veja master kaže na isto mesto. Izbrišete jo lahko z možnostjo -d ukazu git branch:

$ git branch -d hotfix
Deleted branch hotfix (3a0874c).

Sedaj lahko vaše delo preklopite nazaj na vašo vejo dela v teku na težavi #53 in nadaljujete delo na njej.

$ git checkout iss53
Switched to branch "iss53"
$ vim index.html
$ git commit -a -m 'Finish the new footer [issue 53]'
[iss53 ad82d7a] Finish the new footer [issue 53]
1 file changed, 1 insertion(+)
Delo se nadaljuje na `iss53`
Slika 23. Delo se nadaljuje na iss53

Tu je vredno omeniti, da delo, ki ste ga naredili na vaši veji hotfix, ni vsebovano v datotekah vaše veje iss53. Če ga morate povleči notri, lahko združite vašo vejo master v vašo vejo iss53 s pogonom git merge master ali pa lahko počakate, da integrirate te spremembe, dokler se kasneje ne odločite povleči veje iss53 nazaj v master.

Osnovno združevanje

Predpostavimo, da ste se odločili, da je vaša težava #53 končana in pripravljena na združitev v vašo vejo master Da to naredite, boste združili vašo vejo iss53 v master, tako kot ste prej združili vašo vejo hotfix. Vse kar morate narediti, je izvleči vejo, ki jo želite združiti, in nato pognati ukaz git merge:

$ git checkout master
Switched to branch 'master'
$ git merge iss53
Merge made by the 'recursive' strategy.
index.html |    1 +
1 file changed, 1 insertion(+)

To je nekoliko drugače kot združitev hotfix, kar ste naredili prej. V tem primeru se je vaša zgodovina razvoja oddaljila od neke starejše točke. Ker potrditev na veji, na kateri ste, ni neposredni prednik veje, ki jo združujete, mora Git narediti nekaj dela. V tem primeru Git naredi enostavno tri-načinsko združitev z uporabo dveh posnetkov, ki kažeta na vrhova vej in skupnega prednika od teh dveh.

Trije posnetki uporabljeni pri običajni združitvi
Slika 24. Trije posnetki uporabljeni pri običajni združitvi

Namesto samo premikanja kazalca veje naprej, Git ustvari nov posnetek, ki izhaja iz te tri-načinske združitve in avtomatično ustvari novo potrditev, ki kaže nanjo. Ta se imenuje kot potrditev združitve in je posebna v tem, da ima več kot samo eno nadrejeno.

Potrditev združitve
Slika 25. Potrditev združitve

Sedaj, ko je vaše delo združeno, nimate več potrebe po veji iss53. Težavo lahko zaprete v svojem sistemu sledenja težav in vejo izbrišete:

$ git branch -d iss53

Konflikti osnovnega združevanja

Občasno ta proces ne gre gladko. Če ste spremenili isti del neke datoteke na različna načina v dveh vejah, ki ju združujete skupaj, jih Git ne bo mogel gladko združiti. Če je vaš programski popravek za težavo #53 spremenil isti del datoteke kot veja hotfix, boste dobili konflikt združevanja, ki je videti nekako takole:

$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

Git ni avtomatično ustvaril potrditve združevanja. Ustavil je proces, dokler ne rešite konflikta. Če želite videti, katere datoteke niso združene na katerikoli točki po konfliktu združevanja, lahko poženete git status:

$ git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")

Unmerged paths:
  (use "git add <file>..." to mark resolution)

    both modified:      index.html

no changes added to commit (use "git add" and/or "git commit -a")

Karkoli, kar ima konflikte združevanja in niso bili rešeni, je izpisano kot nezdruženo. Git doda standardne označevalce reševanja konfliktov v datoteke, ki imajo konflikte, tako da jih lahko odprete ročno in rešite te konflikte. Vaša datoteka vsebuje razdelek, ki je videti nekako takole:

<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
 please contact us at support@github.com
</div>
>>>>>>> iss53:index.html

To pomeni, da je različica v HEAD (vaše veje master, ker ta je bila, kar ste izvlekli, ko ste pognali svoj ukaz združevanja) vrhnji del tega bloka (vse nad =======), medtem ko je različica v vaši veji iss53 videti kot ves spodnji del. Da rešite konflikt, morate izbrati eno ali drugo stran ali pa združiti vsebino sami. Na primer ta konflikt lahko rešite z zamenjavo celotnega bloka s tem:

<div id="footer">
please contact us at email.support@github.com
</div>

Ta rešitev ima malo vsake od obeh razdelkov in vrstice <<<<<<<, ======= in >>>>>>> so bile v celoti odstranjene. Ko ste rešili vsakega od teh razdelkov v vsaki konfliktni datoteki, poženite git add na vsaki datoteki, da jo označite kot rešeno. Dajanje datoteke v področje priprave jo v Gitu označi kot rešeno.

Če želite uporabiti grafično orodje, da rešite te težave, lahko poženete git mergetool, ki zažene ustrezno vizualno združevalno orodje in vas pelje na sprehod skozi konflikte:

$ git mergetool

This message is displayed because 'merge.tool' is not configured.
See 'git mergetool --tool-help' or 'git help config' for more details.
'git mergetool' will now attempt to use one of the following tools:
opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare vimdiff emerge
Merging:
index.html

Normal merge conflict for 'index.html':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (opendiff):

Če želite namesto privzetega uporabiti drugo orodje združevanja (Git je v tem primeru izbral opendiff, ker je bil ukaz pognan na macOS), lahko pogledate vsa podprta orodja izpisana na vrhu za »one of the following tools«. Samo vpišite ime orodja, ki bi ga raje uporabljali.

Opomba

Če potrebujete naprednejša orodja za reševanje zapletenih konfliktov združevanja, bomo pokrili več o združevanju v Napredno združevanje.

Ko zapustite orodje združevanja, vas Git vpraša, ali je bila združitev uspešna. Če skriptu poveste, da je bila, da datoteko v področje priprave in jo tako za vas označi kot rešeno. Ponovno lahko poženete git status, da potrdite, ali so bili vsi konflikti rešeni:

$ git status
On branch master
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:

    modified:   index.html

Če ste s tem zadovoljni in potrdite, da je bilo dano v področje priprave vse, kar je imelo konflikte, lahko vpišete git commit, da končate potrditev združevanja. Sporočilo potrditve privzeto je videti nekako takole:

Merge branch 'iss53'

Conflicts:
    index.html
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
#	.git/MERGE_HEAD
# and try again.


# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
#	modified:   index.html
#

Če mislite, da bi bilo koristno za druge, ki bodo nekoč gledali to združevanje, lahko to sporočilo potrditve spremenite s podrobnostmi o tem, kako ste rešili združevanje in razložite, zakaj ste naredili te spremembe, če te niso očitne.

scroll-to-top