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 realnem svetu. Sledili boste tem korakom:

  1. Naredite delo na spletni strani.

  2. Ustvarite vejo za novo zgodbo na kateri delate.

  3. Naredite nekaj dela na tej veji.

V tej fazi boste prejeli klic, da je druga težava kritična in potrebujete sprotni popravek. Naredili boste sledeče:

  1. Preklopili na vašo produkcijsko vejo.

  2. Ustvarili vejo, da dodate sprotni popravek.

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

  4. Preklopite nazaj na vašo prvotno zgodbo in nadaljujete delo.

Osnove vej

Najprej recimo, da delate na vašem projektu in imate že nekaj pošiljanj.

A simple commit history.
Slika 18. A simple commit history

Odločili ste se, da boste delali na težavi #53 v kateremkoli težavam-sledilnem sistemu, ki ga vaše podjetje uporablja. Da ustvarite vejo in nanjo preklopite istočasno, 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
Creating a new branch pointer.
Slika 19. Creating a new branch pointer

Delate na vaši spletni strani in naredite nekaj pošiljanj. Da to naredite premakne vejo iss53 naprej, ker ste jo izpisali (to pomeni, vaš HEAD kaže nanjo):

$ vim index.html
$ git commit -a -m 'added a new footer [issue 53]'
The iss53 branch has moved forward with your work.
Slika 20. The iss53 branch has moved forward with your work

Sedaj dobite klic, da je težava s spletno stranjo in jo potrebujete takoj popraviti. Z Git-om vam ni treba nalagati 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 uporabi vašega 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 vmesna faza neposlane spremembe, ki so v konfliktu z vejo, ki jo izpisujete, vam Git ne bo dovolil preklopiti vej. Najbolje je imeti čisto delovno stanje, ko preklapljate veje. Obstajajo načini, da se temu izognete (v glavnem, skrivanje in pošiljanje sprememb), kar bomo pokrili kasneje v [r_git_stashing]. Za sedaj predpostavimo, da ste poslali vse vaše spremembe, tako da lahko preklopite nazaj na vašo vejo master:

$ git checkout master
Switched to branch 'master'

Na tej točki vaš delovni direktorij projekta je točno tak, kakor je bil preden, ste pričeli delati na težavi #53 in sedaj se lahko skoncentrirate na vaš sprotni popravek. To je pomembna točka za zapomniti: ko preklapljate veje, Git ponastavi vaš delovni direktorij, da izgleda kot je, ko ste zadnjič poslali na to vejo. Doda, odstrani in spremeni datoteke avtomatično, da zagotovi, da je vaša delovna kopija taka, kot je izgledala veja na vašem zadnjem pošiljanju vanjo.

Naslednje imate za narediti sprotni popravek. Ustvarimo vejo sprotnega popravka na kateri delate dokler ni končan:

$ git checkout -b hotfix
Switched to a new branch 'hotfix'
$ vim index.html
$ git commit -a -m 'fixed the broken email address'
[hotfix 1fb7853] fixed the broken email address
 1 file changed, 2 insertions(+)
Hotfix branch based on `master`.
Slika 21. Hotfix branch based on master

Lahko poženete vaše teste, zagotovite, da je sprotni popravek, kar želite in ga združite nazaj v vašo vejo master, da naložite v 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(+)

Opazili bste frazo fast-forward'' v tem združevanju. Ker je bilo pošiljanje, kamor kaže veja, ki ste jo združili, direktno gorvodno pošiljanja na katerem ste, Git enostavno premakne kazalec naprej. Da dodamo frazo na drug način, kot poskušate združiti eno pošiljanje z drugim, se to lahko doseže s sledenjem zgodovine prvega pošiljanja, Git poenostavi stvari, tako da prestavi kazalec naprej, ker ni divergentnega dela za združiti skupaj - to se imenuje fast-forward''.

Vaša sprememba je sedaj posnetek pošiljanja, ki kaže na vejo master in lahko naložite popravek.

`master` is fast-forwarded to `hotfix`.
Slika 22. master is fast-forwarded to hotfix

Ko je vaš super pomemben pomemben popravek naložen, ste pripravljeni preklopiti nazaj k delu, ki ste ga delali preden ste bili zmoteni. Vendar najprej boste izbrisali vejo hotfix, ker je ne potrebujete več - veja master kaže na enako lokacijo. Lahko jo izbrišete z opcijo -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 'finished the new footer [issue 53]'
[iss53 ad82d7a] finished the new footer [issue 53]
1 file changed, 1 insertion(+)
Work continues on `iss53`.
Slika 23. Work continues on iss53

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

Basic Merging

Predpostavimo, da ste se odločili, da je vaša težava #53 končana in pripravljena, da je združena 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 izpisati 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 izgleda nekoliko različno kot združitev hotfix, kar ste prej naredili. V tem primeru se je vaša zgodovina razvoja oddaljila od neke starejše točke. Ker pošiljanje na veji, na kateri se nahajate, ni direktni 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 vejo tips in pogostega prednika od dveh.

Three snapshots used in a typical merge.
Slika 24. Three snapshots used in a typical merge

Namesto samo premikanja kazalca veje naprej, Git ustvari nov posnetek, ki rezultira iz te tri-načinske združitve in avtomatično ustvari novo pošiljanje, ki kaže nanjo. Na to se sklicuje kot pošiljanje združitve in je posebno v tem, da ima več kot samo enega starša.

A merge commit.
Slika 25. A merge commit

Vredno je pokazati, da Git določa najboljšega pogostega prednika za uporabo za svojo bazo združitev; to je različno od stareših orodij kot je CVS ali Subversion (pred verzijo 1.5), kjer je razvijalec, ki je delal združitev, moral ugotoviti najboljšo osnovo združitve sam. To naredi združevanje veliko bolj enostavno v Git-u kot v teh starejših sistemih.

Sedaj, ko je vaše delo združeno, nimate več potrebe po veji iss53. Problem lahko zaprete v vašem sistemu sledenja problemov in izbrišete vejo:

$ git branch -d iss53

Basic Merge Conflicts

Včasih ta proces ne gre gladko. Če ste spremenili isti del neke datoteke različno v dveh vejah, ki jih združujete skupaj, jih Git ne bo mogel združiti čisto. Če je vaš popravek za težavo #53 spremenil isti del datoteke kot hotfix, boste dobili konflikt združevanja, ki izgleda 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.

Ti ni avtomatično ustvaril pošiljanja 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 ni bilo rešeno je izpisano kot nezdruženo. Git doda standardne označevalce konflikta ločljivosti k datotekam, ki imajo konflikte, tako da jih lahko odprete ročno in rešite te konflikte. Vaša datoteka vsebuje sekcijo, ki izgleda 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 verzija v HEAD (vaše veje master, ker to je bilo, kar ste imeli izpisano, ko ste pognali vaš ukaz združevanja) je vrhnji del tega bloka (vse nad =======), medtem ko verzija v vaši veji iss53 izgleda kot vse v spodnjem delu. Da rešite konflikt, morate ali izbrati eno stran ali drugo ali 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 ločljivost ima malo vsake sekcije in <<<<<<<, =======, and >>>>>>> vrstice so bile v celoti odstranjene. Ko ste rešili vsakega od teh sekcij v vsaki konfliktni datoteki, poženite git add na vsaki datoteki, da jo označite kot rešeno. Dajanje datoteke v vmesno fazo jo označi kot rešeno v Git-u.

Č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 sprehodi 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 uporabiti drugo orodje združevanja namesto privzetega (Git izbere opendiff v tem primeru, ker je bil ukaz pognan na Mac-u), vidite lahko 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 bolj napredna orodja za reševanje prepredenih konfliktov združevanja, bomo pokrili več o združevanju v [r_advanced_merging].

Ko zapustite orodje združevanja, vas Git vpraša, če je bila združitev uspešna. Če poveste skripti, da je bila, da datoteko v vmesno fazo, da jo označi kot rešeno za vas. Ponovno lahko poženete git status, da potrdite, da 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 vse, kar je imelo s konflikti bilo dano v vmesno fazo, lahko vpišete git commit, da končate pošiljanje združevanja. Sporočilo pošiljanja privzeto izgleda 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
#

To sporočilo lahko spremenite s podrobnostmi o tem, kako ste rešili združevanje, če razmišljate, da bi bilo v pomoč ostalim, da pogledajo to združevanje v prihodnosti - zakaj ste to naredili, če ni očitno.

scroll-to-top