Git
Chapters ▾ 2nd Edition

3.2 Git да тармоқланиш - Тармоқланиш ва бирлашиш асослари

Тармоқланиш ва бирлашиш асослари

Келинг сизни лойиҳангизда фойдаси тегиб қолиши мумкин бўлган иш жараёнини мисол тариқасида қараб чиқамиз. Сизнинг ишингиз бундай қурилган:

  1. сиз сайт устида ишлаябсиз.

  2. Сиз ёзаётган мақолангизга тармоқ яратасиз.

  3. Сиз ушбу тармоқда ишлайсиз.

Сиз шу вақтда критик хатоликни тезроқ тўғрилаш кераклиги ҳақида маълумот олдингиз. Сизнинг ҳаракатларингиз:

  1. Асосий тармоққа ўтиш.

  2. Тўғрилалшни қўшиш учун тармоқ яратасиз.

  3. Тест ўтказилгач тўғриланган кодли тармоқни асосий тармоққа қуясиз.

  4. Аввалги мақола ёзиб ишлаётган тармоғингизга ўтасиз ва ишлашни давом эттирасиз.

Тармоқланиш асослари

Тасаввур қиламиз, сиз лойиҳа устида ишлаябсиз ва бир нечта фиксирлашларга эгасиз.

Фиксирлашларнинг оддий тарихи.
Figure 18. Фиксирлашларнинг оддий тарихи

Сиз хатоликни кузатиш тизимингиздаги #53 хатолик билан ишлашни хулоса қилдингиз дейлик. Тармоқни яратиш учун ва унга бирданига ўтиш учун git checkout командани -b параметри билан бажариш мумкин:

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

Бу қуйидаги билан бир хил:

$ git branch iss53
$ git checkout iss53
Тармоқнинг янги кўрсаткичини яратиш.
Figure 19. Тармоқнинг янги кўрсаткичини яратиш

Сиз ўз сайтингиз билан ишлаябсиз ва фиксирлашларни амалга ошираябсиз. Бу сиз сал аввал iss53 (HEAD уни кўрсатиб туради) тармоққа уланганингиз учун уни илгари силжишига олиб келади.

$ vim index.html
$ git commit -a -m 'added a new footer [issue 53]'
iss53 тармоқ олдинга силжиябди.
Figure 20. iss53 тармоқ олдинга силжиябди

Сиз шу дамда тезда бартараф этилиши керак бўлган сайтингиздаги хавфли очиқ жой ҳақида маълумот оласиз. Git шарофати билан ушбу тузатишни сиз iss53 тармоқдаги қилинган ишлари билан аралаштирмайсиз. Сизга хатто хамма қилинган ишларни орқага қайтариш ҳеч қандай уринишларга ҳожат ҳам қолмайди. Нимаики қилшингиз керак бўлса бу - master тармоққа уланишингиз.

Бироқ буни амалга оширишдан олдин шуни назарла тутингки - агар сизнинг ишчи каталогингиз ёки тайёраланган файллар соҳаси фиксирланмаган ўзгаришларга эга бўлса ва сиз уланмоқчи бўлган тармоқ билан келишмовчиликлар чиқса Git тармоқдан тармоққа уланишга йўл қўймайди. Энг яхшиси лойиҳанинг тоза ҳолатидан тармоққа ўтишдир. Буни айланиб ўтишнинг йўллари мавжуд бу яшириш (stash) ёки фиксирлашларни тўғрилаш (amend), лекин бу ҳақда сал кейинроқ Stashing and Cleaning бўлимда гаплашамиз. Энди тасаввур қилайлик сиз ҳамма ўзгаришларни фиксирладингиз ва асосий тармоққа уланишингиз мумкин:

$ git checkout master
Switched to branch 'master'

Шу вақтдан бошлаб сизнинг ишчи каталогингиз сиз #53 хатолик билан ишлашингиздан олдин қандай бўлган бўлса ана шундай кўринишга эга бўлди. Сиз энди тузатиш билан ишлаш учун диққатингизни жамлашингиз мумкин. Ёдда тутиш муҳим: сиз тармоқга ўтаётган вақтингизда Git ишчи каталогни шу тармоқнинг охирги фиксирлаши кўринишига ўтказади. У ишчи каталогни охирги фиксирлаш кўринишига мослаш учун файлларни ўчиради, қўшади ва автоматик тарзда ўзгартиради.

Энди сиз тузатишни ёзишга ўтишингиз мумкин. Келинг тузатиш учун уни тугатмагунимизча ишлашимизга керак бўладиган тармоқ яратамиз.

$ 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 тармоғи `master` тармоғига асосланган
Figure 21. hotfix тармоғи master тармоғига асосланган

Сиз тестларни юргизиб кутилган натижалар бераётганини текширишингиз ва агар шундай бўлса тузатишни сервердаги ишчи кодларга қўшиш учун уни асосий тармоқ билан бирлаштиришни (merge) амалга оширишингиз мумкин. Бу git merge команда билан бажарилади:

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

Ушбу бирлаштиришда “fast-forward” иборани илғадингизми? Сиз бирлаштирган тармоқ фиксирлаши сиз ишлаган тармоқ фиксирлаши аждоди бўлганлиги сабабли Git уни оддийгина қилиб тармоқ кўрсаткичини олдинга силжитиб қўйди. Бошқа сўзлар билан айтганда агар фиксирлашларни бирлаштиришга кўрсаткични тарих билан тўғри силжитиш орқали эришиш мумкин бўлса Git бирлаштиришни соддалаштиради ва (ишда тармоқланиш йўқ бўлганлиги сабабли) кўрсаткични олдинга суриб қўя қолади. Бу ``fast-forward`` дейилади (тез айлантириш). Энди сизни ўзгаришларингиз — фиксирлаш суръатида (snapshot), бу вақтда master тармоғи айнан ана шуни кўрсатиб турибди ва тузатишни амалиётга қўллаш мумкин.

`master` тармоғи `hotfix` га тез айлантирилган.
Figure 22. master тармоғи hotfix га тез айлантирилган

Сизни муҳим ишингизни амалиётга қўллаганингиздан сўнг сиз аввалги орқага сурилган ишларингизга қайтишингиз мумкин бўлади. Қандай бўлмасин аввал hotfix тармоғини ўчириш керак, сабаби master тармоғи ҳам айнан ана шу тармоқ кўрсатиб турган жойни кўрсатиб турибди ва унинг энди кераги йўқ. Тармоқни ўчириш учун git branch командасини -d параметри билан беринг:

$ 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(+)
`iss53` хатолик билан ишлашни давом эттириш.
Figure 23. iss53 хатолик билан ишлашни давом эттириш

Шунга эътибор бериш жоизки, hotfix тармоғидан ҳамма ўзгаришлар сизни iss53 тармоғингизга ўтказилмаган. Агар уларни қўшиш керак бўлса, сиз Если их нужно включить, вы можете влить ветку master в вашу ветку iss53 командой git merge master, или же вы можете отложить слияние этих изменеий до завершения работы, и затем влить ветку iss53 в master.

Бирлаштириш асослари

Фараз қилайлик, сиз #53 хатолик билан ишлашни тугатдингиз ва уни энди master тармоғига қуйишингиз мумкин. Бунинг учун бироз аввал hotfix тармоғини қандай бирлаштирган бўлсак iss53 тармоғини ҳам худди шундай бирлаштирасиз. Сизнинг қилишингиз керак бўлган иш бу - ўзгаришларни бирлаштиришингиз керак бўлган тармаоққа ўтиб сўнгра 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 бирлаштирилаётган тармоқларнинг икки суръати (snapshot) ва улар учун умумий бош бўлган суръатдан фойдаланиб оддий уч томонламали бирлаштиришни бажаради. сливаемых веток и общего для двух веток родительского снимка.

Бирлаштиришда учта суръатдан фойдаланиш.
Figure 24. Бирлаштиришда учта суръатдан фойдаланиш

Тармоқ кўрсаткичини шундайгина силжитиб қўйиш ўрнига Git уч томонламали бирлаштириш натижавий-суръатини яратиб ундан сўнг автоматик фиксирлашни амалга оширади. Ушбу фиксирлашни аждоди бирдан кўп бўлганлиги боис уни бирлаштириш фиксирлаши дейишади.

Коммит слияния.
Figure 25. Бирлаштириш фиксирлаши

Шуни таъкидлаш жоизки, Git бирлаштиришга асос бўла оладиган қайси аждоддан фойдаланиш яхши эканлигини ўзи аниқлайди. Бу ҳислати уни бошқа эскираётган CVS ёки Subversion (1.5 талқинига қадар) каби ускуналардан фарқлаб туради. Ушбу ускуналарда бирлаштиришни амалга ошираётган яратувчиларнинг ўзлари яхши асосни танлаб олишлари керак бўлади. Бу Git ни кўрсатилган ускуналардагига қараганда бирлаштиришни ақлга сиғмас даражада енгил бажаришини таъминлайди.

Энди иш қуйилганидан кейин iss53 тармоқнинг бошқа кераги йўқ. Сиз хатоликларни назорат қилиш тизимида саволни ёпиб тармоқни ўчиришингиз мумкин:

$ git branch -d iss53

Бирлаштиришдаги асосий келишмовчиликлар

Баъзида ишлар силлиқ ўтавермайди. Агар сиз бирлаштирилаётган икки тармоқда бир хил файлнинг бир хил жойини икки хил тарзда ўзгартирган бўлсангиз 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 (master тармоғингизники, бирлаштириш командасини бериб айнан ана шуни сиз юкладингиз) — блокнинг юқори қисми (барча ======= нинг остидагилар), сизнинг тармоғингиз талқини эса қуйи қисмида келтирилган iss53. Келишмовчиликларга руҳсат бериш учун, икки томондан бирини танлашга ёки уларни ўз хоҳишингизга кўра бирлаштиришингизга тўғри келади. Масалан, сиз барча блокни қуйидаги билан алмаштириш орқали келишмовчиликка руҳсат беришингиз мумкин:

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

Ушбу руҳсатномада ҳар бир қисмдан озгинадан бор, <<<<<<<, ======= ва >>>>>>> сатрлар умуман олиб ташланган. Ҳар бир файлда келишмовчиликларга руҳсат бериб файлларни келишмовчиликлари ҳал бўлганлигини билдириш мақсадида ҳар бир файл учун git add ни ишга туширинг. Файлни тайёрловчи (staging) уни 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):

Агар сиз бирлаштириш унсури сифатида ўзгаришсиз турганини олишни истамасангиз (ушбу ҳолатда команда Mac да берилганлиги сабабли Git opendiff ни олди), барча қўллаб қувватланувчи ускуналар рўйҳати юқоридаги “one of the following tools.” иборадан кейин келтирилган. Фақат ана шу ишлатилиши керак бўлган ускуна номини киритинг.

Note

Бирлаштиришнинг мураккаб келишмовчиликларга руҳсат беришнинг кенгайтирилган унсурлари ҳақидаги батафсил маълумотларни 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

Агар сизни бу қанаотлантирса ва сиз қаерда келишмовчиликлар бўлган бўлса улар тайёрланганлигига (staged) ишонч хосил қилсангиз энди бирлаштиришнинг фиксирлашини тамомлаш учун 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
#

Агар сиз бошқалар келажакда фиксирлашни маъносини тушунишини онсонлаштирмоқчи бўлсангиз ва нимага ва нима қилганлигингиз ҳақида ушбу фиксирлашга қўшимча қўшишингиз мумкин.