Chapters ▾ 2nd Edition

3.2 Git Branching - Eenvoudige vertakking en saamsmelting (Basic Branching and Merging)

Eenvoudige vertakking en saamsmelting (Basic Branching and Merging)

Kom ons stap deur 'n eenvoudige voorbeeld van vertakking (branching) en saamsmelting (merging) met 'n werkvloei (workflow) wat jy in die regte wêreld sal gebruik. Jy sal hierdie stappe volg:

  1. Werk aan 'n webwerf.

  2. Skep 'n tak (branch) vir 'n nuwe storie of taak waaraan jy werk.

  3. Doen bietjie werk in daardie tak.

Dan kry jy 'n oproep dat 'n ander probleem dadelik reggemaak moet word; jy moet 'n vinnige regstelling (hotfix) maak. Jy sal die volgende doen:

  1. Skakel (switch) oor na jou produksie-tak.

  2. Skep 'n tak om die hotfix by te voeg.

  3. Nadat dit getoets is, smelt (merge) die hotfix-tak saam en stuur (push) dit na produksie.

  4. Skakel terug na jou oorspronklike storie en gaan voort met jou werk.

Eenvoudige vertakking (Basic Branching)

Eerstens, kom ons sê jy werk aan jou projek en het reeds 'n paar vasleggings (commits) op die master tak (branch) gemaak.

A simple commit history.
Figure 18. 'n Eenvoudige vasleggingsgeskiedenis (commit history)

Jy het besluit dat jy gaan werk aan probleem #53 in watter stelsel jou maatskappy ook al gebruik om probleme te registreer. Om 'n tak (branch) te skep en dadelik soontoe oor te skakel (checkout), kan jy die git checkout opdrag met die -b opsie uitvoer:

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

Dit is 'n kortpad vir:

$ git branch iss53
$ git checkout iss53
Creating a new branch pointer.
Figure 19. Skep van 'n nuwe tak-wyser (branch pointer)

Jy doen bietjie werk aan jou webwerf en doen 'n paar vasleggings (commits). Deur dit te doen beweeg die iss53 tak vorentoe, omdat jy dit uitgecheck (checked out) het (dit wil sê, jou HEAD wys daarna):

$ vim index.html
$ git commit -a -m 'added a new footer [issue 53]'
The iss53 branch has moved forward with your work.
Figure 20. Die iss53 tak het vorentoe beweeg met jou werk

Nou kry jy die oproep dat daar 'n probleem met die webwerf is, en jy moet dit dadelik regmaak. Met Git hoef jy nie die regstelling gelyktydig vry te stel (deploy) met die iss53 veranderings wat jy gemaak het nie, en jy hoef ook nie baie moeite te doen om daardie veranderings terug te rol (revert) voordat jy kan werk aan jou regstelling in produksie nie. Al wat jy hoef te doen is om terug te skakel (switch) na jou master tak.

Maar voordat jy dit doen, let op dat as jou werkgids (working directory) of voorbereidingsarea (staging area) veranderings bevat wat nog nie vasgelê (committed) is nie en konflik met die tak wat jy wil uitcheck, sal Git jou nie laat oorskakel nie. Dit is die beste om 'n skoon werkende toestand te hê wanneer jy tussen takke skakel. Daar is maniere om hierom te kom (naamlik wegbêre (stashing) en vasleggings-wysiging (commit amending)) wat ons later in Bêre en Skoonmaak (Stashing and Cleaning) sal dek. Vir nou, laat ons aanneem dat jy alle veranderings vasgelê (committed) het, sodat jy kan oorskakel na jou master tak:

$ git checkout master
Switched to branch 'master'

Hierna is jou projek se werkgids (working directory) presies soos dit was voordat jy aan probleem #53 begin werk het, en jy kan daarop konsentreer om jou hotfix te doen. Dit is 'n belangrike punt om te onthou: wanneer jy van takke verander, herstel Git jou werkgids om te lyk soos dit was toe jy laas op daardie tak vasgelê (committed) het. Dit voeg outomaties lêers by, verwyder dit en verander dit om seker te maak dat jou werkskopie presies lyk soos die tak gelyk het by jou laaste vaslegging.

Vervolgens moet jy 'n hotfix doen. Kom ons skep 'n hotfix tak om op te werk totdat dit voltooi is:

$ 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.
Figure 21. Hotfix-tak gebaseer op master

Jy kan jou toetse laat hardloop, jouself verseker dat die hotfix is wat jy wil hê, en uiteindelik die hotfix tak saamsmelt (merge) met jou master-tak om dit na produksie uit te rol. Jy doen dit met die git merge opdrag:

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

Jy sal die uitdrukking “Fast-forward” in daardie saamsmelting (merge) sien. Omdat die vaslegging (commit) C4 waarna die hotfix tak wat jy ingesmelt het, wys, direk voor die vaslegging C2 lê waarop jy jouself bevind, skuif Git bloot die wyser (pointer) vorentoe. Om dit anders te stel: as jy 'n vaslegging probeer saamsmelt (merge) met 'n vaslegging wat bereik kan word deur die geskiedenis van eersgenoemde te volg, vereenvoudig Git dinge deur die wyser vorentoe te skuif aangesien daar geen afwykende werk is om saam te smelt nie — dit word 'n “fast-forward” (vinnig-vorentoe) genoem.

Jou verandering is nou in die momentopname (snapshot) van die vaslegging (commit) waarna die master tak wys, en jy kan jou verandering uitrol (deploy).

master is fast-forwarded to hotfix.
Figure 22. master word vinnig-vorentoe geskuif (fast-forwarded) na hotfix

Nadat jou super-belangrike regstelling uitgerol is, is jy gereed om terug te skakel (switch) na die werk wat jy gedoen het voordat jy onderbreek is. Eers gaan jy egter die hotfix tak uitvee, want jy het dit nie meer nodig nie — die master tak wys na dieselfde plek. Jy kan dit uitvee met die -d opsie op git branch:

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

Nou kan jy terugskakel na jou werk-in-wording tak vir probleem #53 en voortgaan om daaraan te werk.

$ 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.
Figure 23. Werk gaan voort op iss53

Dit is belangrik om hier op te let dat die werk wat jy in die hotfix tak gedoen het, nie in die lêers in jou iss53 tak is nie. As jy dit moet intrek, kan jy die master tak by jou iss53 tak saamsmelt (merge) deur git merge master uit te voer, of jy kan wag om daardie veranderings te integreer totdat jy besluit om die iss53 tak later by master in te trek.

Eenvoudige saamsmelting (Basic Merging)

Veronderstel jy het besluit jou probleem #53 werk is voltooi en gereed om by jou master tak saamgesmelt (merged) te word. Om dit te doen, sal jy jou iss53 tak saamsmelt op dieselfde manier as wat jy vroeër jou hotfix tak saamgesmelt het. Al wat jy hoef te doen is om na die tak oor te skakel (checkout) waarby jy wil saamsmelt, en dan die git merge opdrag uit te voer:

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

Dit lyk 'n bietjie anders as die hotfix saamsmelting wat jy vroeër gedoen het. In hierdie geval het jou ontwikkelingsgeskiedenis vanaf 'n ouer punt afgewyk. Aangesien die vaslegging (commit) op die tak waarop jy is nie 'n direkte voorouer is van die tak wat jy insmelt nie, moet Git bietjie werk doen. In hierdie geval doen Git 'n eenvoudige drierigting-saamsmelting (three-way merge), wat die twee momentopnames (snapshots) gebruik waarna die tak-punte wys, asook die gemeenskaplike voorouer van daardie twee.

Three snapshots used in a typical merge.
Figure 24. Drie momentopnames (snapshots) wat in 'n tipiese saamsmelting gebruik word

In plaas daarvan om die tak-wyser (branch pointer) net vorentoe te skuif, skep Git 'n nuwe momentopname wat die resultaat is van hierdie drierigting-saamsmelting, en skep outomaties 'n nuwe vaslegging (commit) wat daarna wys. Dit word na verwys as 'n saamsmeltingsvaslegging (merge commit), en is spesiaal in die sin dat dit meer as een ouer (parent) het.

A merge commit.
Figure 25. 'n Saamsmeltingsvaslegging (merge commit)

Noudat jou werk saamgesmelt is, is daar nie meer 'n behoefte aan die iss53 tak nie. Jy kan die tak uitvee en dan die kwessie in jou probleem-opsporingstelsel (ticket-tracking system) handmatig sluit:

$ git branch -d iss53

Eenvoudige saamsmeltingskonflikte (Basic Merge Conflicts)

Af en toe verloop hierdie proses nie so glad nie. As jy dieselfde deel van dieselfde lêer verskillend verander het in die twee takke wat jy besig is om saam te smelt, sal Git nie in staat wees om dit skoon saam te smelt (merge) nie. As jou regstelling vir probleem #53 dieselfde deel van 'n lêer as die hotfix verander het, sal jy 'n saamsmeltingskonflik (merge conflict) kry wat min of meer so lyk:

$ 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 het nie outomaties 'n nuwe saamsmeltingsvaslegging (merge commit) geskep nie. Dit het die proses laat wag terwyl jy die konflik oplos. As jy enige tyd na 'n saamsmeltingskonflik wil sien watter lêers nog onsaamgesmelt (unmerged) is, kan jy git status uitvoer:

$ 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")

Enigiets wat saamsmeltingskonflikte (merge conflicts) het en nog nie opgelos is nie, word as onsaamgesmelt (unmerged) gelys. Git voeg standaard konflik-oplossingsmerkers by die lêers wat konflikte bevat, sodat jy hulle handmatig kan oopmaak en die konflikte kan oplos. Jou lêer bevat 'n afdeling wat min of meer so lyk:

<<<<<<< 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

Dit beteken die weergawe in HEAD (jou master tak, want dit is wat jy uitgecheck het toe jy die saamsmelt-opdrag uitgevoer het) is die boonste deel van daardie blok (alles bo die =======), terwyl die weergawe in jou iss53 tak soos alles in die onderste deel lyk. Om die konflik op te los, moet jy óf een kant kies óf self die inhoud saamsmelt. Jy kan byvoorbeeld hierdie konflik oplos deur die hele blok met hierdie te vervang:

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

Hierdie oplossing het 'n bietjie van elke afdeling in, en die <<<<<<<, =======, en >>>>>>> reëls is heeltemal verwyder. Nadat jy elkeen van hierdie afdelings in elke konflikterende lêer opgelos het, voer git add uit op elke lêer om dit as opgelos te merk. Die voorbereiding (staging) van die lêer merk dit as opgelos in Git.

As jy 'n grafiese hulpmiddel wil gebruik om hierdie kwessies op te los, kan jy git mergetool uitvoer, wat 'n toepaslike visuele saamsmelt-instrument aanvuur en jou deur die konflikte sal lei:

$ 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):

As jy 'n ander saamsmelt-instrument (merge tool) wil gebruik in plaas van die verstek een (Git het opendiff in hierdie geval gekies omdat die opdrag op 'n Mac uitgevoer is), kan jy al die ondersteunde gereedskap sien wat bo gelys word na “one of the following tools”. Tik net die naam in van die instrument wat jy verkies om te gebruik.

Note

As jy meer gevorderde instrumente nodig het om komplekse saamsmeltingskonflikte (merge conflicts) op te los, dek ons meer oor saamsmelting in Gevorderde Saamsmelting (Advanced Merging).

Nadat jy die saamsmelt-instrument toemaak, vra Git jou of die saamsmelting suksesvol was. As jy die skrip vertel dat dit was, berei (stage) dit die lêer vir jou voor om dit as opgelos te merk. Jy kan git status weer uitvoer om te verifieer dat al die konflikte opgelos is:

$ 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

As jy tevrede is daarmee, en jy het geverifieer dat alles wat konflikte gehad het nou voorberei (staged) is, kan jy git commit tik om die saamsmeltingsvaslegging (merge commit) te voltooi. Die vasleggingsboodskap lyk by verstek (by default) min of meer so:

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
#

Jy kan daardie boodskap verander met besonderhede oor hoe jy die konflik opgelos het as jy dink dit sal nuttig wees vir ander mense wat in die toekoms na hierdie saamsmelting kyk — hoekom jy gedoen het wat jy gedoen het, as dit nie vanselfsprekend is nie.