13-bo‘lim
Rebase va tarixni tozalash
git rebase qanday ishlaydi, interaktiv rebase bilan kommitlarni tahrirlash va oltin qoida.
Ushbu bo‘lim mundarijasi
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.
git switch feature/savat
git rebase main
Successfully rebased and updated refs/heads/feature/savat.
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 #
Boshqalar bilan ulashilgan kommitlarni hech qachon rebase qilmang.
Agar tarmoq push qilingan va kimdir uni tortib olgan bo'lsa, rebase ularning tarixini buzadi:
- Siz kommitlarni qayta yaratasiz - yangi xeshlar
- Hamkasbingizda eski xeshlar bor
git pullqilganda hamma kommit ikki marta paydo bo'ladi- Chalkashlik va konfliktlar
Xavfsiz: o'z lokal tarmog'ingiz, hech kim tortib olmagan.
Xavfli: main, develop yoki jamoa ishlayotgan istalgan tarmoq.
Rebase qachon foydali? #
# 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.
git rebase -i HEAD~4
Muharrir ochiladi:
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
git log da eng yangi kommit yuqorida turadi.
Rebase ro'yxatida esa eng eski kommit yuqorida. Bu ular qo'llanish tartibi.
Kommitlarni birlashtirish #
pick 3a9c1b5 Savat sahifasi yaratildi
fixup 7d4e2f8 typo
pick 8f3a1d0 Savat mantiqi qo'shildi
fixup 2c7b4e9 yana typo
Saqlab chiqing. Natija:
git log --oneline
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 farqisquash- ikkala kommit xabarini birlashtirib, tahrirlash uchun ochadifixup- ikkinchi kommit xabarini tashlab yuboradi
"typo tuzatildi" kabi xabarlar uchun fixup ideal.
Xabarni o'zgartirish #
pick 3a9c1b5 Savat sahifasi yaratildi
reword 8f3a1d0 savat
Saqlaganingizda Git muharrirni ochib, o'sha kommit xabarini so'raydi.
Kommitni o'chirish #
pick 3a9c1b5 Savat sahifasi yaratildi
drop 7d4e2f8 Test uchun vaqtinchalik kod
pick 8f3a1d0 Savat mantiqi qo'shildi
Tartibni o'zgartirish #
Satrlarni oddiygina joyini almashtiring:
pick 8f3a1d0 Savat mantiqi qo'shildi
pick 3a9c1b5 Savat sahifasi yaratildi
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 #
edit 8f3a1d0 Ikkita ish bitta kommitda
Rebase o'sha kommitda to'xtaydi:
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 #
CONFLICT (content): Merge conflict in manba/savat.php
error: could not apply 8f3a1d0... Savat mantiqi
# 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 beradiRebase paytida chalkashib qolsangiz:
git rebase --abort
Hammasi boshlanishidan oldingi holatga qaytadi. Hech nima yo'qolmaydi.
--autosquash #
Kommit qilishda maxsus prefiks ishlatsangiz, rebase ularni avtomatik joylashtiradi:
git commit --fixup 3a9c1b5
git commit --squash 8f3a1d0
git rebase -i --autosquash HEAD~5
Ro'yxat allaqachon to'g'ri tartibda tayyor bo'ladi.
# Doimiy yoqish
git config --global rebase.autosquash true
--onto - tarmoqni ko'chirish #
Tarmoqni noto'g'ri joydan yaratdingiz:
main
└── develop
└── feature/savat ← aslida main dan bo'lishi kerak edi
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:
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.
# Qisqartma
git config --global alias.pushf "push --force-with-lease"
merge yoki rebase? #
| Vaziyat | Tavsiya |
|---|---|
| Lokal tarmoqni yangilash | rebase |
| PR ni main bilan yangilash | rebase (agar yolg'iz ishlasangiz) |
| Tarmoqni main ga qo'shish | merge |
| Ulashilgan tarmoq | faqat merge |
| Tarixni tozalash | rebase -i |
main yoki develop | hech qachon rebase qilmang |
"Rebase yoki merge" - dasturchilar orasidagi eng eski bahslardan biri.
Ikkalasi ham to'g'ri. Muhimi - jamoa bitta yondashuvni tanlashi va uni hujjatlashtirishi.
Amaliy misol #
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
7f2a9c4 xxx
3d8b1e6 sozlamalar qo'shildi
9a4c7f2 typo
5e1d8b3 profil boshlandi
Bu tarixni PR ga yuborish uyat. Tozalaymiz:
git rebase -i HEAD~4
pick 5e1d8b3 profil boshlandi
fixup 9a4c7f2 typo
pick 3d8b1e6 sozlamalar qo'shildi
fixup 7f2a9c4 xxx
git log --oneline
c8f3a2d sozlamalar qo'shildi
b7e2d1a profil boshlandi
git rebase -i HEAD~2 # reword bilan xabarlarni yaxshilash
git push --force-with-lease
- Tarmoq yarating va to'rtta kommit qiling, ikkitasi "typo" bo'lsin.
git rebase -i HEAD~4bilanfixupqo'llang.git log --onelinebilan natijani ko'ring.rewordbilan bitta kommit xabarini o'zgartiring.dropbilan bitta kommitni o'chiring.mainda yangi kommit qiling, keyin tarmoqdagit rebase mainqiling.git reflogbilan eski kommitlar hali turganini ko'ring.- Ataylab konflikt yarating va
--continue,--abortni sinang. git commit --fixupva--autosquashni sinab ko'ring.- Oltin qoidani o'z so'zlaringiz bilan yozing.
Xulosa #
rebasekommitlarni ko'chirmaydi - ularning nusxasini yaratadi.- Xeshlar o'zgaradi, chunki
parentboshqa bo'ladi. - Oltin qoida: ulashilgan kommitlarni rebase qilmang.
rebase -ibilan kommitlarni birlashtirish, o'chirish, tartibini o'zgartirish va xabarlarni tahrirlash mumkin.fixupkommit xabarini tashlaydi,squashbirlashtiradi.- Konflikt paytida: hal qiling,
add, keyin--continue. --aborthar doim boshlang'ich holatga qaytaradi.- Rebase dan keyin
push --force-with-leaseishlating,--forceemas. mainga qo'shishdamerge, tarmoqni yangilashdarebase.
Keyingi bo'limda stash va cherry-pick ni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
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.