Git
Chapters ▾ 2nd Edition

3.2 Гранење во Git - Основно разгранување и спојување

Основно разгранување и спојување

Ајде да појдеме преку едноставен пример за разгранување и спојување со работниот тек што може да го користите во реалниот свет. Ќе ги следите овие чекори:

  1. Некаква работа на веб-страница.

  2. Создајте гранка за нова приказна на која работите.

  3. Дали некои работи во таа гранка.

Во оваа фаза, ќе добиете повик дека друго прашање е критично и ви треба итна исправа. Ќе го направите следново:

  1. Префрлете се на вашата филијала за производство.

  2. Создајте гранка за да го додадете испратницата.

  3. Откако ќе се тестира, спојте ја филијалата за итна помош и притиснете за производство.

  4. Вратете се во вашата оригинална приказна и продолжете да работите.

Основно разгранување

Прво, да речеме дека работите на вашиот проект и да имате неколку обврски веќе на гранката "господар".

A simple commit history.
Figure 18. A simple commit history

Сте одлучиле дека ќе работите на прашањето # 53 во кој било систем за следење на проблемите што ги користи вашата компанија. За да креирате нова гранка и истовремено да се префрлите на него, можете да ја извршите командата git checkout со прекинувачот` -b`:

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

Ова е кратенка за:

$ git branch iss53
$ git checkout iss53
Creating a new branch pointer.
Figure 19. Creating a new branch pointer

Вие работите на вашата веб-страница и направете некои работи. Со тоа се движи гранката iss53 напред, затоа што сте го одбрале (односно, вашиот HEAD покажува кон него):

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

Сега ќе го добиете повикот дека има проблем со веб-страницата, и треба веднаш да го поправите. Со Git, не мора да го распоредите вашиот фикс заедно со iss53 промените што сте ги направиле, а вие не морате да вложувате многу напори во враќањето на тие промени, пред да можете да работите со примена на вашиот fix за тоа што е во производство. Се што треба да направите е да се префрлите назад во вашата "master" гранка.

Меѓутоа, пред да го направите тоа, имајте во предвид дека ако вашиот работен директориум или област за одложување има непроменети промени кои се во судир со филијалата што ја проверувате, Git нема да ви дозволи да ги префрлите гранките. Најдобро е да имате чиста работна состојба кога ќе ги менувате гранките. Постојат начини да се зафати ова (имено, заострените и извршите измени) кои ќе ги покриеме подоцна, во Stashing and Cleaning. За сега, да претпоставиме дека сте ги направиле сите ваши промени, па можете да се вратите назад во вашата "господарна гранка":

$ git checkout master
Switched to branch 'master'

Во овој момент, вашиот проект работен директориум е токму онака како што беше пред да започнете да работите на број 53, и може да се концентрирате на вашата итна исправа. Ова е важна точка што треба да се запамети: кога ќе ги менувате гранките, Git го ресетира вашиот работен директориум да изгледа како последниот пат кога сте го извршиле во таа гранка. Додава, отстранува и модифицира датотеки автоматски за да бидете сигурни дека вашата работна копија е она што филијалата изгледаше како на вашата последна обврска кон него.

Следно, имате реплика за испраќање. Ајде да создадеме гранка hotfix на која ќе работиме додека не биде завршено:

$ 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 branch based on master

Можете да ги извршите тестовите, осигурајте се дека испратницата е она што сакате, и конечно да се спои филијалата на hotfix назад во вашата" господарна гранка "за да се распореди кон производство. Ова го правиш со командата git merge:

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

Ќе ја забележите фразата ‘` брзо напред '’ во тој спој. Бидејќи обврската C4 укажана на филијалата` hotfix` што сте ја споиле беше непосредно пред извршувањето C2 на кое сте вклучени, Git едноставно го поместува покажувачот напред. За да го фразирате на друг начин, кога ќе се обидете да споите една посветеност со извршување што може да се постигне со следење на историјата на првиот извршител, Git ги поедноставува работите со поместување на покажувачот напред, бидејќи не постои дивергентна работа за спојување заедно - ова се нарекува “fast-forward”.

Вашата промена сега е во снимката на записот што го посочи гранката master, и можете да го распоредите фикс.

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

Откако ќе се распореди вашиот супер-важен фикс, подготвени сте да се вратите назад на работата што ја правите пред да бидете прекинати. Сепак, прво ќе ја избришете филијалата hotfix, затоа што веќе не ви е потребна - поени на" мајсторот "на истото место. Можете да го избришете со опцијата -d за` git branch`:

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

Сега можете да се вратите назад во вашата гранка за работа во прашање # 53 и продолжете да работите на тоа.

$ 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. Work continues on iss53

Вреди да се напомене дека делото што го правите во вашата филијала на "hotfix" не е содржано во датотеките во вашата "iss53" филијала. Ако треба да го повлечете, можете да го споите вашиот master филијала во вашата` iss53` филијала со извршување git merge master, или можете да почекате да ги интегрирате тие промени додека не одлучите да ја повлечете гранката` iss53` назад во господар подоцна.

Basic Merging

Да претпоставиме дека сте решиле дека вашата работа број 53 е завршена и подготвена да се спои во вашата "господарска" гранка. За да го направите тоа, ќе се спои вашата гранка со iss53 во` господар`, исто како што претходно сте ја споиле вашата hotfix branch. Се што треба да направите е да ја проверите гранката во која сакате да се спојат и потоа да ја извршите командата 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(+)

Ова изгледа малку поинакво од спојувањето со hotfix што го направивте порано. Во овој случај, вашата историја на развој се разликува од некоја постара точка. Бидејќи обврската на филијалата на која сте на не е директен предок на гранката со која се спојувате, Git мора да направи некоја работа. Во овој случај, Git прави едноставна комбинација од три начини, користејќи ги двата снимка посочени од филијалата и општиот предок на двете.

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

Наместо само да го поместува покажувачот на гранка напред, Git создава нова слика која резултира од овој тригодишен спој и автоматски креира нова обврска која укажува на тоа. Ова се нарекува спојување и е посебно по тоа што има повеќе од еден родител.

A merge commit.
Figure 25. A merge commit

Вреди да се истакне дека Git го одредува најдобриот заеднички предок што го користи за нејзината спојување; ова е различно од постарите алатки како што се CVS или Subversion (пред верзијата 1.5), каде што програмерот кој го направил спојувањето морал да ја разбере најдобрата база за спојување за себе. Ова го прави спојувањето на многу полесно во Git отколку во овие други системи.

Сега кога вашата работа е споена, немате повеќе потреба за гранката iss53. Можете да го затворите билет во системот за следење на билет и да ја избришете гранката:

$ git branch -d iss53

Basic Merge Conflicts

Понекогаш, овој процес не оди глатко. Ако го промените истиот дел од истата датотека различно во двете гранки со кои се спојувате заедно, Git нема да може да ги спои чисто. Ако вашиот фикс за број # 53 го модифицира истиот дел од датотеката како филијала hotfix, ќе добиете конфликт за спојување кој изгледа вака:

$ 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 не автоматски креира ново спојување. Го запрена процесот додека го решавате конфликтот. Ако сакате да видите кои датотеки не се полнат во било која точка по конфликтот за спојување, можете да го стартувате 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")

Сè што има конфликти на спојување и не е решено е наведено како необликувано. Git додава стандардни маркери за решавање на конфликти во датотеките кои имаат конфликти, па можете рачно да ги отворите и да ги решите тие конфликти. Вашата датотека содржи дел кој изгледа вака:

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

Ова значи дека верзијата во HEAD (вашата` господар` гранка, бидејќи тоа беше она што сте го провериле кога ја извршувавте командата за спојување) е горниот дел од тој блок (сè над '======= ` ), додека верзијата во гранката iss53 изгледа како сè во долниот дел. За да го решите конфликтот, треба да изберете или една или друга страна или да ги споите содржините сами. На пример, може да го разрешите овој конфликт со заменување на целиот блок со ова:

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

Оваа резолуција има малку од секој дел, а <<<<<<< ', ======= и >>>>>>>> линиите се целосно отстранети. Откако ќе го решите секој од овие секции во секоја конфликувана датотека, извршете `git add на секоја датотека за да ја обележите како разрешена. Поставувањето на датотеката го означува како разрешено во Git.

Ако сакате да користите графичка алатка за решавање на овие проблеми, можете да ја стартувате git mergetool, која активира соодветна алатка за визуелно спојување и ве води низ конфликтите:

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

Ако сакате да користите алатка за спојување поинаква од стандардната (Git избра opendiff во овој случај бидејќи командата беше извршена на Mac), можете да ги видите сите поддржани алатки наведени на врвот по` ‘една од следниве алатки . '’ Само внесете го името на алатката која сакате да ја користите.

Ако ви требаат понапредни алатки за решавање на незгодни конфликти, споделуваме повеќе за спојување во Advanced Merging.

Откако ќе излезете од алатката за спојување, Git ве прашува дали спојувањето е успешно. Ако му кажете на сценариото дека е, тој ја фати датотеката за да ја означи како решена за вас. Повторно можете да го стартувате git status за да потврдите дека сите конфликти се решени:

$ 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

Ако сте среќни со тоа, и потврдувате дека сè што имаше конфликти е изведено, можете да напишете `git commit 'за финализирање на спојувањето. Пораката за обврски стандардно изгледа вака:

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
#

Ако мислите дека би било корисно за другите да размислат за ова спојување во иднина, можете да ја модифицирате оваа порака со деталите за тоа како сте решиле спојување и објаснете зошто сте ги направиле промените што сте ги направиле, ако тие не се очигледни.