WisarWisar
Dasturlash kitobi/4-QISM — Git14 daqiqa

4.2-bob: Branch, merge, rebase, conflict yechish

4-QISM — Git va hamkorlik · 2-mavzu


1. Kirish va motivatsiya

Asosiy Git siklini 4.1-bob bildik — lekin u chiziqli edi (bitta yo'nalishda commit'lar). Real ishda esa parallel ishlash kerak: siz yangi feature yozayotganingizda, hamkasbingiz xato tuzatadi, boshqasi boshqa feature ustida — hammasi bir vaqtda, bir-biriga xalaqit bermasdan. Branch (tarmoq) aynan shuni beradi.

Branch — asosiy koddan ajralib chiqib, alohida "parallel olam"da ishlash. Yangi feature'ni branch'da xavfsiz yozasiz; tayyor bo'lsa — asosiy kodga birlashtirasiz (merge). Asosiy kod doim ishlaydigan, barqaror holatda qoladi.

O'xshatish: branch — daryoning shoxobchasi. Asosiy daryo (main) — barqaror oqim. Yangi g'oya uchun shoxobcha (branch) ochasiz, unda erkin tajriba qilasiz (asosiy daryoga ta'sir qilmaydi). Muvaffaqiyatli bo'lsa — shoxobchani asosiy daryoga qaytarasiz (merge). Yomon bo'lsa — shoxobchani tashlab yuborasiz (asosiy daryo zarar ko'rmaydi).

Nega muhim?

  • Parallel ish — bir necha feature/dasturchi bir vaqtda (4.3: hamkorlik).
  • Xavfsiz tajribamain doim barqaror; branch'da erkin sinang.
  • Pull Request 4.3-bob — branch'ni ko'rib chiqib birlashtirish.
  • Git workflow'lar 4.4-bob — branch strategiyasiga asoslanadi.

2. Nazariya — chuqur tushuntirish

2.1. Branch nima?

Branch — commit'lar zanjiridagi ko'rsatkich (pointer — 3.3). main — default branch (asosiy). Yangi branch yaratganda — yangi ko'rsatkich; unda commit qilsangiz, faqat shu branch oldinga siljiydi, main joyida qoladi:

text
        main
         │
  A───B───C
           \
            D───E       feature branch (yangi commit'lar)
            │
         feature

Branch — arzon: Git'da branch faqat ko'rsatkich (40-baytli hash — 3.5), shuning uchun yaratish bir lahza. Boshqa VCS'larda branch — butun nusxa (qimmat). Git'da branch'ni erkin ishlating.

2.2. HEAD — qayerda turibmiz?

HEAD — hozir qaysi branch/commit'da turganingizni ko'rsatadigan maxsus ko'rsatkich. git checkout/git switch bilan branch'lar orasida o'tganda, HEAD ko'chadi va working directory 4.1-bob o'sha branch holatiga o'zgaradi.

HEAD'dan orqaga yurish. Ko'p buyruqlar (reset, rebase, diff) commit'ni HEAD'ga nisbatan ko'rsatishni qulaylashtiradi. ~ (tilde) — necha commit orqaga, ^ (caret) — qaysi ota (merge'da ikki ota bo'ladi):

text
git log HEAD~1      # HEAD'dan 1 commit oldingi (bitta otasi)
git log HEAD~3      # HEAD'dan 3 commit orqada
git log HEAD^       # HEAD ning otasi (= HEAD~1)
git log HEAD^2      # merge commit'ning 2-otasi (qo'shilgan branch)

~ vs ^: HEAD~N — chiziq bo'ylab N qadam orqaga (har doim birinchi ota). HEAD^NN-otani tanlash (faqat merge commit'da farq qiladi, chunki oddiy commit'ning bitta otasi bor). Kundalik ishda ko'pincha HEAD~1, HEAD~2 kifoya.

Detached HEAD (ajralgan HEAD). Agar branch nomiga emas, to'g'ridan-to'g'ri commit hash'iga o'tsangiz (git checkout <hash>), HEAD branch'ga emas, commit'ga "yopishadi" — bu detached HEAD holati. Bu yerda yangi commit qilsangiz, ular hech qaysi branch'ga bog'lanmaydi va boshqa branch'ga o'tsangiz yo'qolib qolishi mumkin:

bash
git checkout a1b2c3d         # eski commit'ni ko'rish uchun o'tdik
# "You are in 'detached HEAD' state" ogohlantirishi chiqadi
# faqat ko'rish (read-only) uchun — xavfsiz

# Agar bu yerda ishni davom ettirmoqchi bo'lsangiz — DARROV branch yarating:
git switch -c eksperiment    # hozirgi holatdan yangi branch (ish saqlanadi)

Detached HEAD — vahima qilmang. U "branch'da emas, commit'da turibsiz" degani — eski holatni ko'rish uchun normal. Faqat yangi ish boshlasangiz, git switch -c <nom> bilan branch'ga "biriktiring", aks holda commit'lar yo'qolishi mumkin.

2.3. Branch buyruqlari

bash
git branch                    # branch'lar ro'yxati (joriy * bilan)
git branch feature-login      # yangi branch yaratish (o'tmasdan)
git switch feature-login      # branch'ga o'tish (zamonaviy)
git switch -c feature-login   # yaratish + o'tish (birga) — eng ko'p
git checkout feature-login    # o'tish (eski usul, hali ishlaydi)
git checkout -b feature-login # yaratish + o'tish (eski)

git branch -d feature-login   # branch o'chirish (merge qilingach)
git branch -D feature-login   # majburan o'chirish (merge qilinmagan)

switch vs checkout: switch — zamonaviy, faqat branch uchun (aniqroq). checkout — eski, ko'p vazifali (branch + fayl restore — 4.1). Yangi kodda switch afzal.

2.4. Merge — birlashtirish

Merge — branch'dagi o'zgarishlarni boshqa branch'ga (odatda main) qaytarib qo'shish:

bash
git switch main               # avval qabul qiluvchi branch'ga o't
git merge feature-login       # feature'ni main'ga birlashtir

Ikki turdagi merge:

Fast-forwardmain o'zgarmagan bo'lsa, shunchaki ko'rsatkichni oldinga suradi (toza, yangi commit yo'q):

text
  main                   main
   │          merge        │
  A───B   +   C───D      A───B───C───D  (chiziqli)

3-way merge — ikkalasi ham o'zgargan bo'lsa, yangi merge commit yaratadi:

text
  A───B───C  (main)         A───B───C───M  (M — merge commit)
       \                         \      /
        D───E (feature)           D───E

2.5. Rebase — tarixni qayta yozish

Rebase — branch commit'larini boshqa branch uchiga ko'chirish (qayta asoslash). Natija — chiziqli, toza tarix (merge commit'siz):

text
  Merge:                      Rebase:
  A───B───C───M               A───B───C───D'───E'
       \     /                         (feature commit'lari
        D───E                          C uchiga ko'chirildi)
bash
git switch feature
git rebase main               # feature commit'larini main uchiga ko'chir

Merge vs Rebase:

  • Merge — tarixni saqlaydi (nima qachon bo'lganini ko'rsatadi), merge commit qo'shadi. Xavfsiz.
  • Rebase — tarixni qayta yozadi (chiziqli, toza), lekin tarixni o'zgartiradi.

Oltin qoida: public (push qilingan, boshqalar ishlayotgan) branch'ni rebase qilmang! Bu boshqalarning tarixini buzadi. Rebase faqat o'zingizning lokal branch'ingiz uchun.

Interaktiv rebase (-i) — tarixni tahrirlash. Rebase'ning yana bir kuchli ishlatilishi — push qilishdan oldin o'z lokal commit'laringizni tozalash: bir nechtasini birlashtirish, xabarlarni tuzatish, keraksizini olib tashlash. git rebase -i <baza> muharrir ochadi va har commit yonida amal tanlanadi:

bash
git rebase -i HEAD~3          # oxirgi 3 commit'ni interaktiv tahrirlash
text
pick   a1b2c3  Login formasi
squash 4d5e6f  Tugma rangini tuzatdim     # oldingiga qo'shib yuboriladi
reword 7g8h9i  login                        # commit xabari qayta yoziladi

Asosiy amallar (muharrirdagi har bir qator boshida):

  • pick — commit'ni o'zgarishsiz qoldirish (default).
  • squash / s — commit'ni oldingisiga birlashtirish (xabarlar qo'shiladi).
  • fixup / f — squash kabi, lekin bu commit xabarini tashlab yuboradi.
  • reword / r — commit'ni saqlash, lekin xabarini qayta yozish.
  • drop / d — commit'ni butunlay olib tashlash.
  • Qatorlar o'rnini almashtirib, commit'lar tartibini ham o'zgartirishingiz mumkin.

Nega kerak? Ish jarayonida "WIP", "tuzatdim", "yana tuzatdim" kabi tartibsiz commit'lar to'planadi. Push 4.3-bob qilishdan oldin ularni squash bilan bitta mazmunli commit'ga jamlasangiz, tarix toza va o'qishli bo'ladi. Bu ham tarixni qayta yozadi — shuning uchun Oltin qoida amal qiladi: faqat push qilinmagan commit'larda ishlating.

2.6. Cherry-pick — bitta commit'ni ko'chirish

Cherry-pick — boshqa branch'dagi bitta (yoki bir nechta) aniq commit'ni joriy branch'ga nusxalash. Butun branch'ni emas, faqat kerakli commit'ni olib kelasiz:

bash
git switch main
git cherry-pick a1b2c3d       # a1b2c3d commit'ini main'ga nusxalash
text
  A───B───C  (main)              A───B───C───E'  (E' — nusxa)
       \                              \
        D───E (feature)                D───E (feature — joyida qoladi)

Qachon kerak? Masalan, hotfix branch'da qilingan bitta tuzatish commit'ini boshqa branch'ga ham olib o'tish kerak bo'lsa — butun branch'ni merge qilmasdan, aynan o'sha commit'ni cherry-pick qilasiz.

Diqqat: cherry-pick commit'ni nusxalaydi (yangi hash bilan), ko'chirmaydi — asl commit o'z branch'ida qoladi. Ikki branch'da bir xil o'zgarish ikki marta paydo bo'lishi keyin merge'da chalkashlik tug'dirishi mumkin, shuning uchun zarur bo'lgandagina ishlating.

2.7. Conflict (ziddiyat) — qachon va nega

Merge conflict — ikki branch bir xil faylning bir xil qatorini har xil o'zgartirganda yuzaga keladi. Git qaysi birini olishni bilmaydi va sizdan so'raydi:

text
  main'da:     const rang = "ko'k";
  feature'da:  const rang = "qizil";
  merge  CONFLICT! Git: "qaysi birini olay?"

Git faylga ikkala variantni belgilab qo'yadi:

text
<<<<<<< HEAD
const rang = "ko'k";        // main'dagi (joriy)
=======
const rang = "qizil";       // feature'dagi (kelayotgan)
>>>>>>> feature

2.8. Conflict'ni yechish

bash
# 1. merge/rebase conflict berdi
git status                    # qaysi fayllar conflictli ko'rsatadi

# 2. Faylni OCH, <<<<< ===== >>>>> belgilarini TOP (2.7)
#    Kerakli variantni qoldir, belgilarni O'CHIR, kodni to'g'rila

# 3. Yechilgan faylni belgila
git add <fayl>

# 4. Yakunlash
git commit                    # merge uchun (xabar avtomatik)
# yoki rebase uchun:
git rebase --continue

Conflict — normal, qo'rqmang. U "ikki kishi bir joyni o'zgartirgan" degani. Belgilarni o'chirib, to'g'ri kodni qoldiring. Chalkashsa — git merge --abort / git rebase --abort bilan bekor qiling.

2.9. Branch ishlash sikli (amaliy)

text
  1. git switch -c feature-x    # main'dan yangi branch
  2. (kod yoz, commit qil)      # 4.1 sikli
  3. git switch main            # main'ga qayt
  4. git merge feature-x        # birlashtir (yoki PR — 4.3)
  5. git branch -d feature-x    # branch'ni o'chir (tugadi)

3. Sintaksis — tez ma'lumotnoma

bash
# Branch
git branch                    # ro'yxat
git switch -c <nom>           # yarat + o't
git switch <nom>              # o't
git branch -d <nom>           # o'chir

# Birlashtirish
git merge <branch>            # merge (xavfsiz, tarix saqlanadi)
git rebase <branch>           # rebase (chiziqli, public'da QILMA)
git rebase -i HEAD~N          # interaktiv: squash/reword/drop (2.5)
git cherry-pick <hash>        # bitta commit'ni nusxalash (2.6)

# Navigatsiya
git switch -c <nom> <hash>    # eski commit'dan branch (detached HEAD — 2.2)
git log HEAD~2                # HEAD'dan 2 commit orqaga (2.2)

# Conflict
git status                    # conflictli fayllar
# <<<<< ===== >>>>> yech  git add  git commit / git rebase --continue
git merge --abort             # bekor qilish

4. Batafsil amaliy namunalar

Misol 1 — Feature branch sikli (2.9)

bash
git switch -c feature-login   # yangi branch (2.3)

echo "login kodi" > login.js
git add login.js
git commit -m "Login sahifasi qo'shildi"

git switch main               # main'ga qayt
git merge feature-login       # birlashtir (2.4)
git branch -d feature-login   # branch tugadi, o'chir
git log --oneline --graph     # tarixni ko'r (4.1)

Misol 2 — Parallel ish (ikki branch — 2.1)

bash
# Feature ustida ishlayapmiz
git switch -c feature-profil
echo "profil" > profil.js && git add . && git commit -m "Profil sahifasi"

# Shoshilinch xato chiqdi — main'da tuzatamiz (feature'ga tegmasdan)
git switch main
git switch -c hotfix-bug
echo "tuzatish" > fix.js && git add . && git commit -m "Kritik xato tuzatildi"
git switch main && git merge hotfix-bug    # tuzatish darrov main'ga

# Keyin feature'ni davom ettiramiz (xalaqit bo'lmadi)
git switch feature-profil

Misol 3 — Conflict yechish (2.7, 2.8)

bash
# main'da rang.js: const rang = "ko'k"
git switch -c feature-rang
# feature'da: const rang = "qizil" qildik, commit
git switch main
# main'da ham o'zgartirdik: const rang = "yashil", commit
git merge feature-rang
# CONFLICT! rang.js'da:
#   <<<<<<< HEAD
#   const rang = "yashil";
#   =======
#   const rang = "qizil";
#   >>>>>>> feature-rang

# Faylni ochib, kerakligini qoldiramiz (masalan "qizil"), belgilarni o'chiramiz:
#   const rang = "qizil";
git add rang.js
git commit -m "rang merge: qizil tanlandi"   # conflict yechildi

Misol 4 — Rebase bilan toza tarix (2.5)

bash
git switch feature-x
git rebase main               # feature commit'larini main uchiga ko'chir
# (conflict bo'lsa: yech  git add  git rebase --continue)

git switch main
git merge feature-x           # endi fast-forward (chiziqli — 2.4)
git log --oneline --graph     # toza, chiziqli tarix

5. To'g'ri va noto'g'ri holatlar

1) mainda to'g'ridan-to'g'ri ishlash

bash
#  main'da to'g'ridan ishlab, barqarorlikni buzish
git switch main && (kod yoz) && git commit

#  feature branch'da (main barqaror qoladi — 2.9)
git switch -c feature-x && (kod yoz) && git commit

2) Public branch'ni rebase qilish

bash
#  boshqalar ishlayotgan branch'ni rebase — tarixni buzadi (2.5)
git rebase main   # (push qilingan, umumiy branch'da)

#  rebase faqat lokal, push qilinmagan branch'da

3) Conflict belgilarini qoldirish

js
//  <<<<< ===== >>>>> belgilarini o'chirmasdan commit (kod buziladi — 2.7)
//  belgilarni o'chir, faqat to'g'ri kodni qoldir (2.8)

4) Merge qilinmagan branch'ni majburan o'chirish

bash
#  -D bilan tasodifan ishni yo'qotish
git branch -D feature-muhim   # (merge qilinmagan!)

#  -d (merge qilingach); -D faqat ataylab tashlanadigan branch

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — CONFLICT (content): Merge conflict in ...

Sababi: ikki branch bir qatorni o'zgartirgan 2.7-bob. Yechimi: faylni oching, <<<<</>>>>> belgilarini yeching, git add, git commit 2.8-bob.

Xato 2 — error: Your local changes would be overwritten

Sababi: saqlanmagan o'zgarishlar branch o'tishga xalaqit. Yechimi: git commit yoki git stash (vaqtincha saqlash), keyin git switch.

Xato 3 — fatal: A branch named 'x' already exists

Sababi: o'sha nomli branch bor. Yechimi: boshqa nom yoki mavjudiga git switch x (yaratmasdan).

Xato 4 — Adashib boshqa branch'da commit qildim

Sababi: noto'g'ri branch'da ish. Yechimi: git log bilan tekshiring; commit'ni to'g'ri branch'ga ko'chirish (cherry-pick — 2.6) yoki ehtiyot bilan reset.

Xato 5 — Rebase chalkashib ketdi

Sababi: ko'p conflict, murakkab rebase. Yechimi: git rebase --abort — boshlang'ich holatga qayting; merge bilan urinib ko'ring.


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • Git asoslari 4.1-bob: branch — commit'lar ustiga quriladi.
  • Pull Request 4.3-bob: branch'ni ko'rib chiqib merge.
  • Git workflow 4.4-bob: Gitflow/trunk — branch strategiyasi.
  • CI/CD 10.5-bob: PR/branch'da avtomatik test.
  • Linked list 3.3-bob: branch — commit zanjiriga ko'rsatkich.
  • Hamkorlik: parallel ish — branch'ning asosiy maqsadi.
  • Conflict — DP/LCS 3.12-bob: git diff/merge ichida matn taqqoslash.

8. Eng yaxshi amaliyotlar (best practices)

  • Har feature/tuzatish — alohida branch (mainda to'g'ridan ishlamang — 2.9).
  • Mazmunli branch nomlari (feature-login, fix-auth, hotfix-...).
  • mainni doim barqaror tuting — faqat tayyor, sinalgan kod merge.
  • Rebase faqat lokal branch'da (public'da qilmang — 2.5).
  • Conflict'dan qo'rqmang — belgilarni yeching, to'g'ri kodni qoldiring 2.8-bob.
  • Kichik, qisqa umrli branch'lar — uzoq yashagan branch ko'p conflict beradi.
  • Merge'dan oldin mainni yangilang (4.3: git pull) — conflict kamayadi.
  • Branch'ni merge'dan keyin o'chiring (-d) — tartib.

9. Amaliy loyiha: "Branch bilan Parallel Ishlash"

Branch, merge, rebase va conflict yechishni amalda mustahkamlash.

Maqsad

Feature branch sikli, merge turlari, conflict yechish va rebase'ni o'zlashtirib, parallel ishlashni simulyatsiya qilish.

Talablar (requirements)

  1. Asosiy loyiha 4.1-bobmainda bir necha commit.
  2. Feature branch: git switch -c bilan, unda 2-3 commit, keyin mainga merge (fast-forward — Misol 1).
  3. Parallel branch'lar: ikki feature branch bir vaqtda; har birida ish; ikkalasini ham merge (3-way merge — 2.4, Misol 2).
  4. Conflict yaratish va yechish: ikki branch bir faylning bir qatorini o'zgartirsin; merge conflict yech (Misol 3).
  5. Hotfix: feature ustida ishlayotib, mainga shoshilinch tuzatish (alohida branch — Misol 2).
  6. Rebase: bitta branch'ni main uchiga rebase qilib, chiziqli tarix (Misol 4); merge bilan farqini ko'ring.
  7. Tarix: git log --oneline --graph --all bilan barcha branch va merge'larni vizual ko'ring.
  8. Branch'larni merge'dan keyin o'chiring (-d).

Maslahatlar (hint)

  • git switch -c <nom> — yarat + o't 2.3-bob.
  • Conflict: faylni oching, <<<<</>>>>> yeching, git add, git commit 2.8-bob.
  • Rebase: git switch feature && git rebase main 2.5-bob.
  • git log --graph --all — barcha branch'lar vizual.
  • Chalkashsa: git merge --abort / git rebase --abort.
  • Rebase faqat lokal branch'da 2.5-bob.

"Tayyor" mezonlari (acceptance criteria)

  • Feature branch yaratish/merge/o'chirish ishlaydi.
  • Fast-forward va 3-way merge ikkalasi ham ko'rsatilgan.
  • Conflict ataylab yaratilgan va to'g'ri yechilgan.
  • Hotfix parallel branch bilan ko'rsatilgan.
  • Rebase bilan chiziqli tarix olingan; merge bilan farqi tushunilgan.
  • git log --graph toza tarix ko'rsatadi.
  • Tugagan branch'lar o'chirilgan.

Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.


10. Xulosa va keyingi bobga ko'prik

Bu bobda Git'ning eng kuchli imkoniyatini — branchni o'rgandik:

  • Branch — commit zanjiriga ko'rsatkich (arzon); parallel, xavfsiz ish. HEAD — qayerdaligimiz.
  • git switch -c (yarat+o't), git merge (birlashtir), git branch -d (o'chir).
  • Merge: fast-forward (chiziqli) yoki 3-way (merge commit). Rebase: chiziqli, toza tarix — lekin public branch'da qilmang.
  • Conflict — ikki branch bir qatorni o'zgartirganda; <<<<</>>>>> belgilarini yechib, git add + commit.
  • Interaktiv rebase (-i) — push'dan oldin commit'larni tozalash (squash/reword/drop). Cherry-pick — bitta commit'ni boshqa branch'ga nusxalash.
  • HEAD navigatsiyaHEAD~N/HEAD^ bilan orqaga; commit hash'iga o'tsangiz — detached HEAD (ish saqlash uchun branch yarating).
  • Best: har feature alohida branch, main barqaror, kichik branch'lar.

Keyingi bob — 4.3-bob: GitHub — remote, push, pull, Pull Request, fork. Lokal Git'ni bildik; endi uni bulutga (GitHub) ulaymiz: kodni yuklash (push), olish (pull), va eng muhimi — Pull Request (kodni ko'rib chiqib birlashtirish — jamoaviy ishning yuragi).


Foydalanilgan rasmiy/ishonchli manbalar

  • git-scm.com — branch, merge, rebase rasmiy hujjatlari
  • Atlassian Git Tutorial — merge vs rebase, conflict resolution
  • Pro Git kitobi — branching model

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
4.2-bob: Branch, merge, rebase, conflict yechish — Wisar