13-bo‘lim

Rebase va tarixni tozalash

git rebase qanday ishlaydi, interaktiv rebase bilan kommitlarni tahrirlash va oltin qoida.

🕑 17 daqiqa o‘qish 📄 709 so‘z 👁 6 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Rebase nima qiladi?
  2. Oltin qoida
  3. Rebase qachon foydali?
  4. Interaktiv rebase
  5. Kommitlarni birlashtirish
  6. Xabarni o'zgartirish
  7. Kommitni o'chirish
  8. Tartibni o'zgartirish
  9. Kommitni bo'lish
  10. Konflikt paytida
  11. --autosquash
  12. --onto - tarmoqni ko'chirish
  13. Force push
  14. merge yoki rebase?
  15. Amaliy misol
  16. Xulosa

rebase - Git ning eng kuchli va eng ko'p qo'rqinchli buyrug'i. Uni tushunsangiz, tarixni istalgancha toza saqlaysiz.

Rebase nima qiladi? #

merge ikki tarmoqni birlashtiradi. rebase esa kommitlaringizni ko'chiradi.

Boshlang'ich holat main feature git merge main Merge kommit qo'shildi Tarix shoxlangan Xeshlar o'zgarmadi git rebase main A' B' Kommitlar oxiriga ko'chirildi Tarix chiziqli Yangi xeshlar yaratildi
Rebase kommitlarni ko'chirmaydi - ularning nusxasini yaratadi
Terminal
git switch feature/savat
git rebase main
Natija
Successfully rebased and updated refs/heads/feature/savat.
Rebase kommitlarni "ko'chirmaydi"

Bu muhim nozik jihat. Rebase har bir kommitni qaytadan qo'llaydi va yangi kommit yaratadi.

Xeshlar o'zgaradi, chunki parent boshqa. Mazmun bir xil, lekin bu boshqa kommitlar.

Eskilari git reflog da hali turadi.

Oltin qoida #

Rebase ning oltin qoidasi

Boshqalar bilan ulashilgan kommitlarni hech qachon rebase qilmang.

Agar tarmoq push qilingan va kimdir uni tortib olgan bo'lsa, rebase ularning tarixini buzadi:

  1. Siz kommitlarni qayta yaratasiz - yangi xeshlar
  2. Hamkasbingizda eski xeshlar bor
  3. git pull qilganda hamma kommit ikki marta paydo bo'ladi
  4. Chalkashlik va konfliktlar

Xavfsiz: o'z lokal tarmog'ingiz, hech kim tortib olmagan. Xavfli: main, develop yoki jamoa ishlayotgan istalgan tarmoq.

Rebase qachon foydali? #

Terminal
# Tarmog'ingizni main dagi yangiliklar bilan yangilash
git switch feature/savat
git fetch origin
git rebase origin/main

Bu merge ga qaraganda toza natija beradi: PR da faqat sizning o'zgarishlaringiz ko'rinadi, keraksiz merge kommitlar yo'q.

Interaktiv rebase #

Bu eng foydali imkoniyat - tarixni tahrirlash.

Terminal
git rebase -i HEAD~4

Muharrir ochiladi:

Natija
pick 3a9c1b5 Savat sahifasi yaratildi
pick 7d4e2f8 typo
pick 8f3a1d0 Savat mantiqi qo'shildi
pick 2c7b4e9 yana typo

# Rebase c9d2e71..2c7b4e9 onto c9d2e71 (4 commands)
#
# Commands:
# p, pick   = kommitni o'z holida qoldirish
# r, reword = kommitni qoldirish, xabarini o'zgartirish
# e, edit   = kommitda to'xtash va uni tahrirlash
# s, squash = oldingi kommit bilan birlashtirish (xabarlar qo'shiladi)
# f, fixup  = squash kabi, lekin bu kommit xabari tashlanadi
# d, drop   = kommitni butunlay o'chirish
Tartib teskari

git log da eng yangi kommit yuqorida turadi.

Rebase ro'yxatida esa eng eski kommit yuqorida. Bu ular qo'llanish tartibi.

Kommitlarni birlashtirish #

Natija
pick 3a9c1b5 Savat sahifasi yaratildi
fixup 7d4e2f8 typo
pick 8f3a1d0 Savat mantiqi qo'shildi
fixup 2c7b4e9 yana typo

Saqlab chiqing. Natija:

Terminal
git log --oneline
Natija
b4f8e2a Savat mantiqi qo'shildi
9c1d5a3 Savat sahifasi yaratildi
c9d2e71 Kitoblar sahifasi qo'shildi

Ikkita "typo" kommiti yo'qoldi - ular tegishli kommitlarga qo'shildi.

squash va fixup farqi
  • squash - ikkala kommit xabarini birlashtirib, tahrirlash uchun ochadi
  • fixup - ikkinchi kommit xabarini tashlab yuboradi

"typo tuzatildi" kabi xabarlar uchun fixup ideal.

Xabarni o'zgartirish #

Natija
pick 3a9c1b5 Savat sahifasi yaratildi
reword 8f3a1d0 savat

Saqlaganingizda Git muharrirni ochib, o'sha kommit xabarini so'raydi.

Kommitni o'chirish #

Natija
pick 3a9c1b5 Savat sahifasi yaratildi
drop 7d4e2f8 Test uchun vaqtinchalik kod
pick 8f3a1d0 Savat mantiqi qo'shildi

Tartibni o'zgartirish #

Satrlarni oddiygina joyini almashtiring:

Natija
pick 8f3a1d0 Savat mantiqi qo'shildi
pick 3a9c1b5 Savat sahifasi yaratildi
Tartib o'zgartirish konflikt berishi mumkin

Agar kommitlar bir-biriga bog'liq bo'lsa (ikkinchisi birinchisining kodiga tayanadi), tartibni almashtirish konfliktga olib keladi.

Bu normal - konfliktni hal qilib davom eting.

Kommitni bo'lish #

Natija
edit 8f3a1d0 Ikkita ish bitta kommitda

Rebase o'sha kommitda to'xtaydi:

Terminal
git reset HEAD~1              # kommitni ochamiz
git add manba/savat.php
git commit -m "Savat mantiqi"
git add manba/hisobot.php
git commit -m "Hisobot mantiqi"
git rebase --continue

Konflikt paytida #

Natija
CONFLICT (content): Merge conflict in manba/savat.php
error: could not apply 8f3a1d0... Savat mantiqi
Terminal
# 1. Konfliktni hal qiling
nano manba/savat.php

# 2. Sahnaga qo'ying
git add manba/savat.php

# 3. Davom eting
git rebase --continue

# Bu kommitni tashlab ketish
git rebase --skip

# Butun rebase ni bekor qilish
git rebase --abort
--abort har doim yordam beradi

Rebase paytida chalkashib qolsangiz:

Terminal
git rebase --abort

Hammasi boshlanishidan oldingi holatga qaytadi. Hech nima yo'qolmaydi.

--autosquash #

Kommit qilishda maxsus prefiks ishlatsangiz, rebase ularni avtomatik joylashtiradi:

Terminal
git commit --fixup 3a9c1b5
git commit --squash 8f3a1d0

git rebase -i --autosquash HEAD~5

Ro'yxat allaqachon to'g'ri tartibda tayyor bo'ladi.

Terminal
# Doimiy yoqish
git config --global rebase.autosquash true

--onto - tarmoqni ko'chirish #

Tarmoqni noto'g'ri joydan yaratdingiz:

Natija
main
 └── develop
       └── feature/savat   ← aslida main dan bo'lishi kerak edi
Terminal
git rebase --onto main develop feature/savat

Bu "feature/savat ni develop dan ajratib, main ga ulash" degani.

Force push #

Rebase dan keyin push qilish uchun:

Terminal
git push --force-with-lease
--force emas, --force-with-lease

--force shartsiz yozadi - agar hamkasbingiz siz fetch qilgandan keyin push qilgan bo'lsa, uning ishi yo'qoladi.

--force-with-lease avval tekshiradi: "server hali ham men bilgan holatdami?" Agar yo'q bo'lsa - rad etadi.

Har doim --force-with-lease ishlating.

Terminal
# Qisqartma
git config --global alias.pushf "push --force-with-lease"

merge yoki rebase? #

VaziyatTavsiya
Lokal tarmoqni yangilashrebase
PR ni main bilan yangilashrebase (agar yolg'iz ishlasangiz)
Tarmoqni main ga qo'shishmerge
Ulashilgan tarmoqfaqat merge
Tarixni tozalashrebase -i
main yoki develophech qachon rebase qilmang
Jamoada kelishib oling

"Rebase yoki merge" - dasturchilar orasidagi eng eski bahslardan biri.

Ikkalasi ham to'g'ri. Muhimi - jamoa bitta yondashuvni tanlashi va uni hujjatlashtirishi.

Amaliy misol #

Terminal
git switch -c feature/profil
echo "profil" > profil.php && git add . && git commit -m "profil boshlandi"
echo "rasm" >> profil.php && git commit -am "typo"
echo "sozlama" >> profil.php && git commit -am "sozlamalar qo'shildi"
echo "." >> profil.php && git commit -am "xxx"

git log --oneline
Natija
7f2a9c4 xxx
3d8b1e6 sozlamalar qo'shildi
9a4c7f2 typo
5e1d8b3 profil boshlandi

Bu tarixni PR ga yuborish uyat. Tozalaymiz:

Terminal
git rebase -i HEAD~4
Natija
pick   5e1d8b3 profil boshlandi
fixup  9a4c7f2 typo
pick   3d8b1e6 sozlamalar qo'shildi
fixup  7f2a9c4 xxx
Terminal
git log --oneline
Natija
c8f3a2d sozlamalar qo'shildi
b7e2d1a profil boshlandi
Terminal
git rebase -i HEAD~2   # reword bilan xabarlarni yaxshilash
git push --force-with-lease
Amaliy topshiriq
  1. Tarmoq yarating va to'rtta kommit qiling, ikkitasi "typo" bo'lsin.
  2. git rebase -i HEAD~4 bilan fixup qo'llang.
  3. git log --oneline bilan natijani ko'ring.
  4. reword bilan bitta kommit xabarini o'zgartiring.
  5. drop bilan bitta kommitni o'chiring.
  6. main da yangi kommit qiling, keyin tarmoqda git rebase main qiling.
  7. git reflog bilan eski kommitlar hali turganini ko'ring.
  8. Ataylab konflikt yarating va --continue, --abort ni sinang.
  9. git commit --fixup va --autosquash ni sinab ko'ring.
  10. Oltin qoidani o'z so'zlaringiz bilan yozing.

Xulosa #

  • rebase kommitlarni ko'chirmaydi - ularning nusxasini yaratadi.
  • Xeshlar o'zgaradi, chunki parent boshqa bo'ladi.
  • Oltin qoida: ulashilgan kommitlarni rebase qilmang.
  • rebase -i bilan kommitlarni birlashtirish, o'chirish, tartibini o'zgartirish va xabarlarni tahrirlash mumkin.
  • fixup kommit xabarini tashlaydi, squash birlashtiradi.
  • Konflikt paytida: hal qiling, add, keyin --continue.
  • --abort har doim boshlang'ich holatga qaytaradi.
  • Rebase dan keyin push --force-with-lease ishlating, --force emas.
  • main ga qo'shishda merge, tarmoqni yangilashda rebase.

Keyingi bo'limda stash va cherry-pick ni o'rganamiz.

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.