9-bo‘lim

Birlashtirish va konfliktlar

Fast-forward va uch tomonlama merge, konflikt nima uchun chiqadi va uni qanday to'g'ri hal qilish kerak.

🕑 17 daqiqa o‘qish 📄 733 so‘z 👁 5 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Oddiy birlashtirish
  2. Fast-forward nima?
  3. Uch tomonlama merge
  4. Merge turini boshqarish
  5. Konflikt
  6. Konflikt belgilari
  7. Konfliktni hal qilish
  8. Konflikt paytidagi holat
  9. Merge ni bekor qilish
  10. Bir tomonni tanlash
  11. Uch tomonni birga ko'rish
  12. Vizual vosita
  13. Konfliktdan qochish
  14. Amaliy misol
  15. Xulosa

Tarmoqda ish tugagach, uni asosiy tarmoqqa qo'shish kerak. Bu jarayon merge (birlashtirish) deb ataladi.

Oddiy birlashtirish #

Terminal
# Qabul qiluvchi tarmoqqa o'tamiz
git switch main

# Tarmoqni birlashtiramiz
git merge feature/qidiruv
Natija
Updating c9d2e71..7d4e2f8
Fast-forward
 manba/qidiruv.php        | 1 +
 manba/qidiruv-mantiq.php | 1 +
 2 files changed, 2 insertions(+)
Yo'nalishga e'tibor bering

git merge X - "X ni joriy tarmoqqa qo'sh" degani.

Ya'ni avval maqsad tarmog'iga o'tish, keyin merge qilish kerak. Boshlovchilar ko'pincha buni teskari qiladi.

Fast-forward nima? #

Fast-forward: main hech qayoqqa ketmagan edi Oldin main feature Keyin main, feature ko'rsatkich oldinga suriladi Yangi kommit yo'q main ko'rsatkichi shunchaki oldinga suriladi Tarix chiziqli qoladi
Fast-forward faqat main da yangi kommit bo'lmaganda mumkin

Uch tomonlama merge #

Agar main da ham yangi kommitlar bo'lsa, Git merge kommit yaratadi:

Ikkala tarmoqda ham yangi kommit bor umumiy ota main davom etdi feature merge kommit ikkita otasi bor
Merge kommit - yagona ikkita otasi bo'lgan kommit turi
Terminal
git merge feature/savat
Natija
Merge made by the 'ort' strategy.
 manba/savat.php | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

Git muharrirni ochib, xabar so'raydi:

Natija
Merge branch 'feature/savat' into main

Odatda standart xabar yetarli.

Merge turini boshqarish #

Terminal
# Har doim merge kommit yaratish (fast-forward bo'lsa ham)
git merge --no-ff feature/savat

# Faqat fast-forward bo'lsa birlashtirish, aks holda to'xtash
git merge --ff-only feature/savat

# Barcha kommitlarni bitta kommitga jamlash
git merge --squash feature/savat
git commit -m "Savat imkoniyati qo'shildi"
--no-ff nima uchun foydali?

Fast-forward da tarix chiziqli bo'ladi va "bu ish qaysi tarmoqda qilingani" ko'rinmaydi.

--no-ff bilan har bir imkoniyat tarixda alohida "pufak" bo'lib qoladi:

Natija
*   4b8e2a1 Merge branch 'feature/savat'
|\
| * 7d4e2f8 Savat mantiqi
| * 3a9c1b5 Savat sahifasi
|/
* c9d2e71 Kitoblar sahifasi

Ko'p jamoalar main ga merge qilishda har doim --no-ff ishlatadi.

--squash qachon kerak?

Tarmoqda 15 ta kommit bor: "ishlamayapti", "yana urinish", "endi ishladi", "typo".

--squash ularning hammasini bitta toza kommitga aylantiradi. main tarixi o'qilishi oson bo'ladi.

Kamchiligi: tarmoqning ichki tarixi yo'qoladi.

Konflikt #

Konflikt ikkala tarmoqda ham bir xil faylning bir xil satri o'zgartirilganda chiqadi.

Terminal
git merge feature/dizayn
Natija
Auto-merging manba/index.php
CONFLICT (content): Merge conflict in manba/index.php
Automatic merge failed; fix conflicts and then commit the result.
Git ko'p narsani o'zi hal qiladi

Agar siz faylning boshini, hamkasbingiz oxirini o'zgartirgan bo'lsa - Git ikkalasini avtomatik birlashtiradi.

Konflikt faqat aynan bir xil satrlar o'zgarganda chiqadi. Bu boshlovchilar o'ylaganidan ancha kam uchraydi.

Konflikt belgilari #

Fayl ichi shunday ko'rinadi:

PHP
<?php

$sarlavha = 'Kutubxona';

<<<<<<< HEAD
echo '<h1 class="asosiy">' . $sarlavha . '</h1>';
=======
echo '<h1 id="sarlavha">' . $sarlavha . '</h1>';
>>>>>>> feature/dizayn

// Oxiri
BelgiMa'nosi
<<<<<<< HEADJoriy tarmoqdagi (sizning) versiya boshlanishi
=======Ajratuvchi
>>>>>>> feature/dizaynKelayotgan tarmoq versiyasi oxiri

Konfliktni hal qilish #

1-qadam. Faylni oching va belgilarni o'chirib, kerakli kodni qoldiring:

PHP
<?php

$sarlavha = 'Kutubxona';

echo '<h1 id="sarlavha" class="asosiy">' . $sarlavha . '</h1>';

// Oxiri
Belgilarni albatta o'chiring

<<<<<<<, =======, >>>>>>> satrlari kodda qolib ketmasin.

Bu eng ko'p uchraydigan xato - sayt shundan keyin oq ekran ko'rsatadi. Kommitdan oldin qidirib chiqing:

Terminal
git diff --check
grep -rn "<<<<<<<" .

2-qadam. Faylni sahnaga qo'ying:

Terminal
git add manba/index.php

3-qadam. Merge ni yakunlang:

Terminal
git commit
Natija
[main 9c2f5a8] Merge branch 'feature/dizayn'

Konflikt paytidagi holat #

Terminal
git status
Natija
On branch main
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   manba/index.php
Terminal
# Faqat konfliktli fayllarni ko'rish
git diff --name-only --diff-filter=U

Merge ni bekor qilish #

Terminal
git merge --abort

Hammasi merge boshlanishidan oldingi holatga qaytadi.

Vahima qilmang

Konflikt ko'rganda ko'p boshlovchi qo'rqib ketadi. Aslida:

  1. git merge --abort har doim orqaga qaytaradi
  2. Hech narsa yo'qolmaydi
  3. Konfliktni istalgancha marta qayta boshlash mumkin

Konflikt - xato emas, normal ish jarayoni.

Bir tomonni tanlash #

Ba'zan butun faylning bitta versiyasi kerak:

Terminal
# O'zimizning versiyani olish
git checkout --ours manba/index.php

# Kelayotgan versiyani olish
git checkout --theirs manba/index.php

git add manba/index.php
ours va theirs chalkashtiradi

merge paytida:

  • ours - siz turgan tarmoq (main)
  • theirs - birlashtirilayotgan tarmoq (feature)

rebase paytida esa teskari bo'ladi! Bu Git ning eng chalkash joyi.

Shubhalansangiz - faylni ochib o'z ko'zingiz bilan ko'ring.

Uch tomonni birga ko'rish #

Terminal
git config --global merge.conflictstyle diff3

Endi konflikt shunday ko'rinadi:

PHP
<<<<<<< HEAD
echo '<h1 class="asosiy">' . $sarlavha . '</h1>';
||||||| umumiy ota
echo $sarlavha;
=======
echo '<h1 id="sarlavha">' . $sarlavha . '</h1>';
>>>>>>> feature/dizayn
Bu sozlamani yoqing

O'rtadagi qism - asl holat. Uni ko'rish har bir tomon nimani o'zgartirganini tushunishga juda yordam beradi.

Masalan: yuqorida ikkala tomon ham echo $sarlavha; ni HTML bilan o'ragan - faqat atributlar boshqacha. Yechim aniq: ikkalasini birlashtirish.

Vizual vosita #

Terminal
git mergetool

Sozlash:

Terminal
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
git config --global mergetool.keepBackup false

Konfliktdan qochish #

Amaliy maslahatlar
  1. Kichik va tez-tez kommit qiling - kam kod, kam konflikt.
  2. Tarmoqni tez-tez yangilang:
    Terminal
     git switch feature/savat
     git merge main

    Har kuni shunday qiling - konflikt kichik bo'ladi.

  3. Tarmoqni uzoq ushlab turmang - bir haftadan oshmasin.
  4. Jamoada gaplashing - kim qaysi faylda ishlayotganini biling.
  5. Formatlash qoidalarini kelishib oling - .editorconfig va avtomatik formatlovchi konfliktlarning yarmini yo'q qiladi.

Amaliy misol #

Terminal
# Ikkita tarmoq bir xil faylni o'zgartiradi
git switch -c tarmoq-a
echo "A versiyasi" > matn.txt
git commit -am "A qo'shildi"

git switch main
git switch -c tarmoq-b
echo "B versiyasi" > matn.txt
git commit -am "B qo'shildi"

git switch main
git merge tarmoq-a          # muvaffaqiyatli
git merge tarmoq-b          # KONFLIKT
Natija
CONFLICT (add/add): Merge conflict in matn.txt
Terminal
cat matn.txt
Natija
<<<<<<< HEAD
A versiyasi
=======
B versiyasi
>>>>>>> tarmoq-b
Terminal
echo "A va B versiyalari" > matn.txt
git add matn.txt
git commit -m "Merge: ikkala versiya birlashtirildi"
git log --oneline --graph
Natija
*   5f8a2c1 Merge: ikkala versiya birlashtirildi
|\
| * 3b7e9d4 B qo'shildi
* | 8c1f5a2 A qo'shildi
|/
* c9d2e71 Boshlang'ich holat
Amaliy topshiriq
  1. main da matn.txt yarating va kommit qiling.
  2. tarmoq-a yarating, faylni o'zgartiring, kommit qiling.
  3. main ga qayting, tarmoq-b yarating, shu satrni boshqacha o'zgartiring va kommit qiling.
  4. main ga qayting va tarmoq-a ni merge qiling - fast-forward bo'lishini ko'ring.
  5. tarmoq-b ni merge qiling - konfliktni oling.
  6. git status bilan holatni ko'ring.
  7. git merge --abort bilan bekor qiling, keyin qaytadan boshlang.
  8. Konfliktni qo'lda hal qiling va kommit qiling.
  9. merge.conflictstyle diff3 ni yoqing va farqni ko'ring.
  10. --no-ff va --squash variantlarini sinab ko'ring.

Xulosa #

  • git merge X - X ni joriy tarmoqqa qo'shadi.
  • Fast-forward - qabul qiluvchi tarmoqda yangi kommit bo'lmaganda.
  • Merge kommit - ikkita otasi bo'lgan yagona kommit turi.
  • --no-ff har doim merge kommit yaratadi, tarixda tarmoq ko'rinadi.
  • --squash barcha kommitlarni bittaga jamlaydi.
  • Konflikt faqat bir xil satrlar o'zgarganda chiqadi.
  • Konflikt belgilarini (<<<<<<<, =======, >>>>>>>) albatta o'chiring.
  • git merge --abort har doim orqaga qaytaradi.
  • merge.conflictstyle diff3 asl holatni ham ko'rsatadi - uni yoqing.
  • Tez-tez merge qilish konfliktlarni kichik va oson qiladi.

Keyingi bo'limda masofaviy repozitoriylar bilan ishlashni boshlaymiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.