Branch va birlashtirish (merge)
Branch (o'zbekcha: shox yoki tarmoq) โ Git'ning eng kuchli imkoniyatlaridan biri. U sizga asosiy kodga tegmasdan, alohida yo'nalishda ishlashga imkon beradi. Yangi funksiya yozmoqchimisiz, yoki xatoni tuzatmoqchimisiz โ buni alohida branch'da qilib, tayyor bo'lgach asosiy kodga birlashtirasiz. Ushbu darsda branch yaratish, ular orasida o'tish, birlashtirish (merge) va merge konfliktini hal qilishni chuqur o'rganamiz.
Branch nima va nega kerak?
Har bir Git ombori (repository) kamida bitta branch'ga ega. An'anaviy nomi master edi, hozirgi zamonaviy loyihalarda esa ko'pincha main deb ataladi. Bu โ asosiy, ishonchli kod turadigan yo'nalish.
Branch โ bu commitlar (o'zgarishlar tarixi) ustidagi siljib boruvchi ko'rsatkich (pointer). Har safar yangi commit qilganingizda, joriy branch avtomatik ravishda oxirgi commit'ga siljiydi. Yangi branch ochsangiz, siz shu paytdagi commit'dan yangi mustaqil yo'nalish boshlaysiz.
Branch nima uchun kerak? Bir nechta amaliy sabab:
- Xavfsiz eksperiment. Yangi g'oyani asosiy kodga zarar bermasdan sinab ko'rasiz. Ishlamasa โ branch'ni o'chirasiz, asosiy kod toza qoladi.
- Parallel ishlash. Bir vaqtning o'zida bir necha funksiya (masalan, bittasi
login, boshqasiprofil) alohida branch'larda mustaqil rivojlanadi. - Jamoaviy tartib. Har bir dasturchi o'z branch'ida ishlaydi, bir-birining kodini buzmaydi. Tayyor bo'lgach hamma o'zinikini
mainga birlashtiradi. - Barqaror asosiy kod.
mainbranch doim ishlaydigan, chiqarishga tayyor holatda saqlanadi. Yarim tayyor kod alohida branch'larda turadi.
Mavjud branch'larni ko'rish: git branch
Omborda qanday branch'lar borligini va hozir qaysi biridasiz โ buni git branch buyrug'i ko'rsatadi. Joriy branch oldida yulduzcha (*) turadi:
$ git branch
* main
Bu omborda hozircha bitta main branch bor va biz aynan undamiz. Barcha branch'larni (masofaviylarni ham) batafsil ko'rish uchun:
$ git branch -a
* main
feature-login
remotes/origin/main
Bu yerda mahalliy main va feature-login, hamda masofaviy (GitHub'dagi) origin/main ko'rinadi.
Yangi branch yaratish: git branch nomi
Yangi branch yaratish uchun uning nomini beramiz. Masalan, feature-login nomli branch ochamiz:
$ git branch feature-login
Diqqat: bu buyruq branch'ni faqat yaratadi, lekin sizni unga o'tkazmaydi. Siz hali ham eski branch'dasiz. Buni git branch bilan tekshiring:
$ git branch
feature-login
* main
Ko'rib turganingizdek, feature-login yaratildi, lekin yulduzcha hali mainda.
feature-login, fix-header-bug, update-readme. Ko'plab jamoalar nomlarda prefiks ishlatadi: feature/, fix/, hotfix/ โ masalan feature/user-profile.Branch'lar orasida o'tish: git checkout va git switch
Yaratilgan branch'ga o'tish uchun ikki xil yo'l bor. Eskiroq va universal usul โ git checkout:
$ git checkout feature-login
Switched to branch 'feature-login'
Endi git branch yulduzchani feature-loginda ko'rsatadi. Bu branch'da qilgan har bir commit faqat shu branch tarixiga tushadi.
Zamonaviy Git (2.23-versiyadan boshlab) yanada tushunarli buyruq taqdim etdi โ git switch. U faqat branch almashtirish uchun mo'ljallangan (chalkashlik kamroq):
$ git switch feature-login
Switched to branch 'feature-login'
git checkout juda ko'p vazifani bajaradi: branch almashtirish, fayllarni tiklash, ma'lum commit'ni ko'rish. Bu chalkashlikka olib kelardi. Shuning uchun Git jamoasi uni ikkiga bo'ldi: branch almashtirish uchun git switch, fayllarni tiklash uchun esa git restore. Yangi loyihalarda switch va restoreni afzal ko'ring, lekin checkout ham hamma joyda ishlaydi.Yaratish va o'tishni bir buyruqda: -b va -c
Ko'pincha branch'ni yaratib, darhol unga o'tmoqchi bo'lasiz. Har safar ikki buyruq yozish shart emas โ buni bitta buyruqda qilish mumkin. checkout uchun -b bayrog'i:
$ git checkout -b feature-login
Switched to a new branch 'feature-login'
Zamonaviy switchda xuddi shu narsa -c (create) bayrog'i bilan qilinadi:
$ git switch -c feature-login
Switched to a new branch 'feature-login'
Ikkalasi ham: yangi feature-login branch'ini yaratadi va sizni darhol unga o'tkazadi. Bu โ amaliyotda eng ko'p ishlatiladigan usul.
Branch'da ishlash: to'liq amaliy misol
Keling, to'liq oqimni ko'rib chiqamiz. mainda turibmiz, yangi funksiya uchun branch ochamiz, o'zgartiramiz va commit qilamiz:
# 1. Yangi branch yaratib, unga o'tamiz
$ git switch -c feature-login
Switched to a new branch 'feature-login'
# 2. Fayllarni tahrirlaymiz (masalan, login.js yaratamiz)
# ... kod yozamiz ...
# 3. O'zgarishni saqlaymiz
$ git add login.js
$ git commit -m 'Login sahifasini qoshdim'
[feature-login 1a2b3c4] Login sahifasini qoshdim
1 file changed, 40 insertions(+)
Endi login.js faqat feature-login branch'ida mavjud. Agar mainga qaytsangiz, u fayl u yerda ko'rinmaydi (chunki commit boshqa branch'da):
$ git switch main
Switched to branch 'main'
$ ls
index.html style.css
# login.js bu yerda yoq โ u feature-login branchida qoldi
git stash bilan vaqtincha yashiring). Aks holda saqlanmagan o'zgarishlar bilan branch almashtirmoqchi bo'lsangiz, Git ogohlantirish beradi va ba'zan almashtirishga yo'l qo'ymaydi. git stashni keyingi darsda ko'ramiz.Branch'larni birlashtirish: git merge
Branch'da ish tugagach, uni asosiy kodga qo'shish kerak. Bu jarayon merge (birlashtirish) deb ataladi. Muhim qoida: siz qaysi branch'ga birlashtirmoqchi bo'lsangiz, avval o'sha branch'ga o'tasiz, keyin kerakli branch'ni unga tortasiz.
Masalan, feature-loginni mainga birlashtiramiz. Avval mainga o'tamiz, keyin feature-loginni birlashtiramiz:
# 1. Maqsad branchiga (main) otamiz
$ git switch main
Switched to branch 'main'
# 2. feature-login ni main ga birlashtiramiz
$ git merge feature-login
Updating a1b2c3d..1a2b3c4
Fast-forward
login.js | 40 ++++++++++++++++++++++
1 file changed, 40 insertions(+)
Endi login.js va uning barcha o'zgarishlari mainga qo'shildi. Merge muvaffaqiyatli tugadi.
main branch feature-login ajralib chiqqandan beri o'zgarmagan bo'lsa. Bu holda Git shunchaki main ko'rsatkichini oldinga suradi โ yangi commit yaratmaydi.Agar ikkala branch ham parallel o'zgargan bo'lsa, Git merge commit deb ataladigan maxsus commit yaratadi. Bu ikki tarixni bittaga bog'laydigan tugun. Bunda tahrirlagich ochilib, sizdan birlashtirish xabarini so'raydi (yoki -m bilan berasiz):
$ git merge feature-login
Merge made by the 'ort' strategy.
login.js | 40 ++++++++++++++++++++++
1 file changed, 40 insertions(+)
Merge konflikti nima?
Merge har doim ham silliq o'tmaydi. Merge konflikti โ bu ikkala branch'da bir xil faylning bir xil qatori turli xil tarzda o'zgartirilganda yuz beradi. Git qaysi versiyani tanlashni bilmaydi va sizdan qo'lda hal qilishni so'raydi.
Masalan, mainda kimdir index.htmlning 1-qatorini o'zgartirdi, siz esa feature-loginda xuddi shu qatorni boshqacha o'zgartirdingiz. Merge qilganda:
$ git merge feature-login
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
Git to'xtaydi va aytadi: konfliktni o'zingiz hal qiling. Hozirgi holatni git status ham ko'rsatadi:
$ git status
On branch main
You have unmerged paths.
(fix conflicts and run 'git commit')
Unmerged paths:
(use 'git add <file>...' to mark resolution)
both modified: index.html
Merge konfliktini hal qilish
Konfliktli faylni matn tahrirlagichda ochsangiz, Git maxsus belgilar qo'yganini ko'rasiz. Ular ikkala versiyani ko'rsatadi:
<<<<<<< HEAD
<h1>Bosh sahifa</h1>
=======
<h1>Xush kelibsiz!</h1>
>>>>>>> feature-login
Bu belgilarni tushunamiz:
<<<<<<< HEADโ joriy branch (siz turgan, ya'nimain) versiyasining boshi;=======โ ikki versiyani ajratuvchi chiziq;>>>>>>> feature-loginโ birlashtirilayotgan branch versiyasining oxiri.
Konfliktni hal qilish โ bu shu belgilarni o'chirib, faylni to'g'ri yakuniy holatga keltirish demakdir. Siz bir versiyani tanlashingiz, yoki ikkalasini birlashtirishingiz mumkin. Masalan, quyidagi variantni qoldiramiz:
<h1>Xush kelibsiz!</h1>
Barcha <<<, ===, >>> belgilarini butunlay olib tashlaganingizga ishonch hosil qiling. Keyin faylni saqlab, hal qilinganini Git'ga bildiramiz:
# konflikt hal qilingan faylni belgilaymiz
$ git add index.html
# birlashtirishni yakunlaymiz
$ git commit -m 'index.html dagi merge konfliktini hal qildim'
[main 5f6g7h8] index.html dagi merge konfliktini hal qildim
git merge --abort. Bu birlashtirishni to'liq to'xtatadi va omborni merge boshlanishidan oldingi holatga qaytaradi.Keraksiz branch'ni o'chirish: git branch -d
Branch birlashtirilib, endi kerak bo'lmasa, uni o'chirib tozalik saqlash yaxshi odat. Muvaffaqiyatli birlashtirilgan branch'ni -d (delete) bilan o'chiramiz:
$ git branch -d feature-login
Deleted branch feature-login (was 1a2b3c4).
Agar branch hali hech qayerga birlashtirilmagan bo'lsa, -d uni o'chirmaydi โ Git ish yo'qolib qolishidan ogohlantiradi:
$ git branch -d feature-test
error: The branch 'feature-test' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature-test'.
Agar rostdan ham keraksiz bo'lsa va birlashtirilmagan ishni yo'qotishga rozimisiz โ katta -D (majburiy o'chirish) ishlatiladi:
$ git branch -D feature-test
Deleted branch feature-test (was 9z8y7x6).
-D (katta harf) branch'ni birlashtirilmagan bo'lsa ham majburan o'chiradi. Undagi commitlar boshqa branch'da bo'lmasa โ butunlay yo'qoladi. Shuning uchun -Dni faqat o'zgarishlar kerak emasligiga to'liq ishonganingizda ishlating.Xulosa
Ushbu darsda branch bilan ishlashning to'liq davrini o'rgandik:
- Branch โ commitlar ustidagi siljib boruvchi ko'rsatkich; alohida, xavfsiz yo'nalishda ishlash imkoni;
git branchโ branch'larni ko'rish,git branch nomiโ yaratish;git checkout nomiyoki zamonaviygit switch nomiโ branch'ga o'tish;git checkout -b nomiyokigit switch -c nomiโ yaratib, darhol o'tish;git merge nomiโ branch'ni joriy branch'ga birlashtirish (avval maqsad branch'ga o'tib olasiz);- merge konflikti โ bir xil qator ikki xil o'zgarganda yuzaga keladi; belgilarni qo'lda hal qilib,
git add+git commitbilan yakunlanadi; git branch -d nomiโ birlashtirilgan branch'ni o'chirish,-Dโ majburiy o'chirish.
Branch'lar Git ish oqimining yuragidir. Keyingi darsda mahalliy omborni GitHub bilan bog'lab, kodni internetga yuborishni o'rganamiz.