Mundarija (36)
- Bu darsda
- 1. Nega bu kerak?
- 2. Birinchi rebase
- 2.1 Vaziyat
- 2.2 git rebase main
- 2.3 SHA'lar o'zgardi!
- 2.4 Endi merge — fast-forward
- 3. Rebase ichkaridan
- 4. Rebase paytida conflict
- 4.1 Conflict chiqadi
- 4.2 Holatni o'qish
- 4.3 Markerlar — va teskari "biz"
- 4.4 --abort — boshiga qaytish
- 4.5 Yechish va --continue
- 5. --skip va avtomatik tashlab ketish
- 5.1 Commit allaqachon main da bo'lsa
- 5.2 --skip — o'zingiz tashlab ketish
- 6. Oltin qoida
- 6.1 Qoida
- 6.2 Nega?
- 7. Merge yoki rebase?
- 8. git pull --rebase — kelajakka qisqa ko'prik
- 9. Ko'p uchraydigan xatolar
- 9.1 Iflos ishchi papka
- 9.2 add qilmay --continue
- 9.3 Rebase yo'q paytda --continue
- 9.4 Noto'g'ri yo'nalish
- 9.5 Rebase'dan keyin "commitlarim yo'qoldi"
- 10. Mashqlar
- 1-mashq (oson): Rostmi yoki yolg'on?
- 2-mashq (o'rta): Bo'sh joylarni to'ldiring
- 3-mashq (qiyin): Ikki argumentli rebase
- 4-mashq: Portfolio qadami — branch'ni yangilab qo'shish
- 11. Real ishda
- Xulosa
- Manbalar
Git rebase: tarixni chiziqlash va oltin qoida
Qisqacha:
git rebase mainjoriy branch'dagi commitlarni olib, ularnimainning eng oxirgi commiti ustiga qaytadan qo'yadi. Natijada tarix to'g'ri chiziq bo'ladi va keyingi merge fast-forward bilan o'tadi. Lekin rebase yangi commitlar yaratadi — SHA'lar o'zgaradi. Shuning uchun oltin qoida: boshqalar ham ishlatayotgan (GitHub'ga yuborilgan, umumiy) branch'ni hech qachon rebase qilmang.
Bu darsda
- Rebase commitlarni qanday "ko'chirishini" va nega SHA'lar o'zgarishini tushuntirasiz.
git rebase mainbilan branch'ingizni yangilab, fast-forward merge qilasiz.- Rebase paytidagi conflict'ni
--continue,--abortva--skipbilan boshqarasiz. - Oltin qoidani va uning sababini aniq ayta olasiz.
- Merge va rebase'ni solishtirib, qaysi vaziyatda qaysi biri qulayligini tanlaysiz.
Oldin bilishingiz kerak: Merge: fast-forward va uch tomonlama birlashtirish, Conflictlarni yechish amaliyoti, HEAD, refs va detached HEAD.
1. Nega bu kerak?
«Bahor» tarixiga qarang. Oxirgi uch darsda uch marta merge qildik va tarixda uchta "cho'ntak" paydo bo'ldi. Kichik loyihada bu muammo emas. Lekin o'nta dasturchi har kuni ishlaydigan loyihada git log --graph rel-yo'llar tugunidek chalkash bo'lib ketadi. "Bu o'zgarish qachon kirgan?" degan savolga javob topish qiyinlashadi.
Bundan tashqari, merge commitlarning ko'pi hech qanday ma'lumot bermaydi. "Merge branch 'main' into feature/..." — bu faqat "men yangiliklarni oldim" degani. Tarixda shovqin ko'payadi.
Git'da ikkinchi yo'l bor — rebase (asosni almashtirish). G'ishtli devorni tasavvur qiling. Siz o'z qatoringizni devorning eski joyiga qo'yishni boshlagan edingiz, bu orada boshqalar devorni ikki qator ko'tarib qo'ydi. Rebase — g'ishtlaringizni olib, devorning yangi, eng yuqori qatoriga qayta terish. Natijada devor tekis, bitta chiziq.
Merge darsida --ff-only xatosi ham shu yo'lni maslahat bergan edi: git rebase. Bugun uni ochamiz.
2. Birinchi rebase
2.1 Vaziyat
Menyuga ichimliklar bo'limini qo'shish uchun branch ochamiz va ikki commit qilamiz:
cd ~/kurs/bahor
git switch -c feature/ichimliklar
echo '<h2>Ichimliklar</h2>' >> menyu/index.html
git commit -am "Menyu: ichimliklar bo'limini qo'sh"
echo "<p>Ko'k choy — 5 000 so'm</p>" >> menyu/index.html
git commit -am "Menyu: ko'k choy qo'sh"Switched to a new branch 'feature/ichimliklar'
[feature/ichimliklar df4ac38] Menyu: ichimliklar bo'limini qo'sh
1 file changed, 1 insertion(+)
[feature/ichimliklar afcf200] Menyu: ko'k choy qo'sh
1 file changed, 1 insertion(+)Shu orada main da bosh sahifaga ish vaqti yozildi (git switch main, keyin index.html ga qator va commit):
[main 37c92ec] Bosh sahifa: ish vaqtini qo'sh
1 file changed, 1 insertion(+)Tarix ayrildi:
git log --oneline --graph --all -5* 37c92ec (HEAD -> main) Bosh sahifa: ish vaqtini qo'sh
| * afcf200 (feature/ichimliklar) Menyu: ko'k choy qo'sh
| * df4ac38 Menyu: ichimliklar bo'limini qo'sh
|/
* 7658a99 Merge branch 'fix/lagmon-narxi'
|\
| * 6eb3409 Menyu: lag'mon narxini 30 000 qil-5 — faqat oxirgi beshta commit. Pastdagi |\ — o'tgan darsdagi merge'ning boshlanishi, u bizga hozir kerak emas.
gitGraph
commit id: "7658a99 merge"
branch feature/ichimliklar
commit id: "df4ac38 bo'lim"
commit id: "afcf200 choy"
checkout main
commit id: "37c92ec ish vaqti"Nimaga qarang: feature/ichimliklar 7658a99 dan o'sgan — bu uning asosi (base). main esa o'shandan beri bir qadam yurgan. Oddiy git merge qilsak, yana bitta merge commit va yana bitta cho'ntak paydo bo'ladi.
2.2 git rebase main
Rebase'ni ko'chiriladigan branch'da turib qilamiz — ya'ni o'z branch'imizda:
git switch feature/ichimliklar
git rebase mainSwitched to branch 'feature/ichimliklar'
Successfully rebased and updated refs/heads/feature/ichimliklar.Tarjimasi: "Muvaffaqiyatli rebase qilindi va refs/heads/feature/ichimliklar yangilandi". Terminalda bir lahza Rebasing (1/2), Rebasing (2/2) yozuvlari ham chaqnab o'tadi — Git har commitni navbat bilan ko'chirayotganini ko'rsatadi, keyin bu yozuv ustidan yangisi yoziladi.
Tarixga qaraymiz:
git log --oneline --graph --all -5* e666b2d (HEAD -> feature/ichimliklar) Menyu: ko'k choy qo'sh
* 6761532 Menyu: ichimliklar bo'limini qo'sh
* 37c92ec (main) Bosh sahifa: ish vaqtini qo'sh
* 7658a99 Merge branch 'fix/lagmon-narxi'
|\
| * 6eb3409 Menyu: lag'mon narxini 30 000 qilAyrilish yo'qoldi. Ikkala commitimiz endi 37c92ec ustida turibdi — go'yo biz ishni ish vaqti yozilgandan keyin boshlagandek.
gitGraph
commit id: "7658a99 merge"
commit id: "37c92ec ish vaqti"
branch feature/ichimliklar
commit id: "6761532 bo'lim"
commit id: "e666b2d choy"Nimaga qarang: branch'ning asosi 7658a99 dan 37c92ec ga ko'chdi. Nomi "rebase" — "re-base", asosni qayta belgilash — shundan.
2.3 SHA'lar o'zgardi!
Diqqat bilan solishtiring:
| Commit | Rebase'dan oldin | Rebase'dan keyin |
|---|---|---|
| Ichimliklar bo'limi | df4ac38 |
6761532 |
| Ko'k choy | afcf200 |
e666b2d |
Xabarlar, fayldagi o'zgarishlar — bir xil. SHA'lar esa boshqa. Nega?
Git ichkaridan darsini eslang: commit SHA'si commitning butun mazmunidan hisoblanadi — daraxt, muallif, sana, xabar va ota commit. Rebase'dan keyin birinchi commitning otasi boshqa (7658a99 emas, 37c92ec). Demak SHA ham boshqa. Ikkinchisining otasi esa birinchisi — u ham o'zgardi.
Ya'ni rebase commitlarni "ko'chirmaydi". U yangi commitlar yaratadi: eskilarining nusxasini yangi asos ustiga. Eski commitlar esa hech qaerga ketmaydi — ularga shunchaki endi hech bir branch ishora qilmaydi. Git rebase'dan oldingi joyni ORIG_HEAD da eslab qoladi (HEAD va refs darsidan):
git log --oneline -1 ORIG_HEADafcf200 Menyu: ko'k choy qo'shEski uch shu yerda. Rebase natijasi yoqmasa, git reset --hard ORIG_HEAD hammasini qaytaradi (reset darsidan). Bu "orqaga yo'l" haqida ko'proq — Reflog darsida.
2.4 Endi merge — fast-forward
git switch main
git merge feature/ichimliklarSwitched to branch 'main'
Updating 37c92ec..e666b2d
Fast-forward
menyu/index.html | 2 ++
1 file changed, 2 insertions(+)Merge commit yo'q! main shunchaki oldinga surildi, chunki rebase'dan keyin feature/ichimliklar uning to'g'ridan-to'g'ri davomi edi.
git log --oneline --graph -5
git branch -d feature/ichimliklar* e666b2d (HEAD -> main, feature/ichimliklar) Menyu: ko'k choy qo'sh
* 6761532 Menyu: ichimliklar bo'limini qo'sh
* 37c92ec Bosh sahifa: ish vaqtini qo'sh
* 7658a99 Merge branch 'fix/lagmon-narxi'
|\
| * 6eb3409 Menyu: lag'mon narxini 30 000 qil
Deleted branch feature/ichimliklar (was e666b2d).Mana "rebase + fast-forward" usuli: tarix tekis chiziq, har commit o'z joyida.
Tekshirib ko'ring: Rebase'dan keyin
df4ac38commiti o'chib ketdimi?
Javob
Yo'q. U hali ham .git ichida bor — shuning uchun ORIG_HEAD orqali ko'ra oldik. Faqat endi hech bir branch unga ishora qilmaydi. Bunday "yetim" commitlarni Git bir necha haftadan keyin tozalab yuboradi, lekin ungacha ularni qaytarish mumkin.
3. Rebase ichkaridan
Rebase uch qadamda ishlaydi:
- Git joriy branch va
mainning umumiy ajdodini topadi (merge base). - Branch'dagi ajdoddan keyingi commitlarni vaqtincha chetga oladi va branch'ni
mainuchiga qo'yadi. - Chetga olingan commitlarni birma-bir, tartib bilan qaytadan qo'llaydi — har biri yangi commit bo'ladi.
flowchart LR
A["Umumiy ajdodni<br/>topish"] --> B["Commitlarni<br/>chetga olish"]
B --> C["main uchiga<br/>o'tish"]
C --> D["1-commitni<br/>qo'llash"]
D --> E["2-commitni<br/>qo'llash"]
E --> F["Branch nomini<br/>surish"]
D -. conflict .-> G["To'xtab,<br/>sizni kutadi"]Nimaga qarang: commitlar bitta-bitta qo'llanadi. Shuning uchun rebase'dagi conflict bitta commit ustida chiqadi — va bir rebase davomida bir necha marta chiqishi mumkin. Merge'da esa hamma conflict bir marta, bir joyda chiqadi.
4. Rebase paytida conflict
4.1 Conflict chiqadi
Somsa haqida ikki ish bir qatorga tegdi. feature/somsa-turlari da somsa turlari yozildi va izoh qo'shildi:
[feature/somsa-turlari 9d5596d] Menyu: somsa turlarini qo'sh
1 file changed, 1 insertion(+), 1 deletion(-)
[feature/somsa-turlari 4ffb780] Menyu: qovoqli somsa izohini qo'sh
1 file changed, 1 insertion(+)main da esa shu orada somsa narxi 9 000 bo'ldi (a73d1c1). Branch'da turib rebase qilamiz:
git rebase mainAuto-merging menyu/index.html
CONFLICT (content): Merge conflict in menyu/index.html
error: could not apply 9d5596d... Menyu: somsa turlarini qo'sh
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Recorded preimage for 'menyu/index.html'
Could not apply 9d5596d... # Menyu: somsa turlarini qo'shTarjimasi: "9d5596d ni qo'llab bo'lmadi. Hamma ziddiyatlarni qo'lda yeching, git add/rm bilan belgilang, keyin git rebase --continue ni ishga tushiring. Buning o'rniga bu commitni o'tkazib yuborish mumkin: git rebase --skip. Rebase'dan oldingi holatga qaytish uchun: git rebase --abort". Recorded preimage — Conflictlar darsida yoqqan rerere ishi.
Git birinchi commit ustida to'xtadi. Ikkinchisi hali navbatda.
4.2 Holatni o'qish
git statusinteractive rebase in progress; onto a73d1c1
Last command done (1 command done):
pick 9d5596d # Menyu: somsa turlarini qo'sh
Next command to do (1 remaining command):
pick 4ffb780 # Menyu: qovoqli somsa izohini qo'sh
(use "git rebase --edit-todo" to view and edit)
You are currently rebasing branch 'feature/somsa-turlari' on 'a73d1c1'.
(fix conflicts and then run "git rebase --continue")
(use "git rebase --skip" to skip this patch)
(use "git rebase --abort" to check out the original branch)
Unmerged paths:
(use "git restore --staged <file>..." to unstage)
(use "git add <file>..." to mark resolution)
both modified: menyu/index.html
no changes added to commit (use "git add" and/or "git commit -a")Yuqori qismi yangi: "a73d1c1 ustiga rebase ketmoqda. Bajarilgan buyruq: pick 9d5596d. Keyingisi: pick 4ffb780". pick — "shu commitni ol va qo'lla". Bu ro'yxat bilan keyingi darsda o'zingiz ishlaysiz. Hozir muhimi: bir commit bajarildi (conflict bilan), bittasi kutyapti.
4.3 Markerlar — va teskari "biz"
cat menyu/index.html<h1>Menyu</h1>
<p>Osh — 38 000 so'm (qazi bilan)</p>
<p>Lag'mon — 30 000 so'm (qo'l lag'mon)</p>
<<<<<<< HEAD
<p>Somsa — 9 000 so'm</p>
||||||| parent of 9d5596d (Menyu: somsa turlarini qo'sh)
<p>Somsa — 8 000 so'm</p>
=======
<p>Somsa — 8 000 so'm (go'shtli, qovoqli)</p>
>>>>>>> 9d5596d (Menyu: somsa turlarini qo'sh)
<p>Shashlik — 15 000 so'm</p>
<h2>Ichimliklar</h2>
<p>Ko'k choy — 5 000 so'm</p>Diqqat! Bu yerda HEAD — main ning versiyasi (9 000), sizning commitingiz esa pastda, >>>>>>> 9d5596d. Merge'dagiga teskari.
Sababi «Rebase ichkaridan» bo'limida: rebase paytida Git avval main uchiga o'tadi, keyin sizning commitlaringizni unga qo'llaydi. Demak HEAD — qurilayotgan yangi asos, "kelayotgan" esa sizning commitingiz. Shu sababli rebase'da --ours — main tomoni, --theirs — sizning commitingiz. Conflictlar darsidagi ogohlantirish shu edi. Chalkashmaslik uchun so'zlarga emas, markerdagi nom va SHA'ga qarang.
||||||| ostida asl qator: parent of 9d5596d — "commitimizning otasidagi holat".
4.4 --abort — boshiga qaytish
Avval xavfsiz chiqish yo'lini sinaymiz:
git rebase --abort
git log --oneline --graph --all -4* a73d1c1 (main) Menyu: somsa narxini 9 000 qil
| * 4ffb780 (HEAD -> feature/somsa-turlari) Menyu: qovoqli somsa izohini qo'sh
| * 9d5596d Menyu: somsa turlarini qo'sh
|/
* e666b2d Menyu: ko'k choy qo'shHammasi rebase'dan oldingidek: eski SHA'lar, ayrilgan tarix. --abort rebase'ning istalgan joyida ishlaydi.
4.5 Yechish va --continue
Qaytadan git rebase main — yana o'sha conflict. Bu safar yechamiz. Ikkala o'zgarish kerak: yangi narx va turlar. Fayldagi somsa qatorini shunday qoldiramiz:
<p>Somsa — 9 000 so'm (go'shtli, qovoqli)</p>Markerlarni o'chirib, faylni saqlaymiz. Keyin — merge'dagidan farqli — git commit emas, git rebase --continue:
git add menyu/index.html
git rebase --continueVS Code'da commit xabari ochiladi (Menyu: somsa turlarini qo'sh) — o'zgartirmay yopamiz:
Recorded resolution for 'menyu/index.html'.
[detached HEAD d6cee25] Menyu: somsa turlarini qo'sh
1 file changed, 1 insertion(+), 1 deletion(-)
Successfully rebased and updated refs/heads/feature/somsa-turlari.[detached HEAD d6cee25] — rebase davomida Git branch'da emas, to'g'ridan-to'g'ri commitlarda ishlaydi (detached HEAD). Oxirida branch nomi yangi uchga ko'chiriladi. Ikkinchi commit conflictsiz qo'llandi.
git log --oneline --graph --all -4* 95b5e40 (HEAD -> feature/somsa-turlari) Menyu: qovoqli somsa izohini qo'sh
* d6cee25 Menyu: somsa turlarini qo'sh
* a73d1c1 (main) Menyu: somsa narxini 9 000 qil
* e666b2d Menyu: ko'k choy qo'shEndi git switch main va git merge feature/somsa-turlari — fast-forward (Updating a73d1c1..95b5e40).
Diqqat: Rebase paytida
git commityozmang. Conflictni yechgach —git addvagit rebase --continue. Git commitni o'zi yaratadi va keyingisiga o'tadi.
Tekshirib ko'ring: Rebase paytidagi conflict'da
<<<<<<< HEADostidagi qator kimniki — sizning branch'ingiznikimi yokimainnikimi?
Javob
main niki. Rebase main uchida turib sizning commitlaringizni birma-bir qo'llaydi, shuning uchun HEAD — yangi asos. Sizning commitingiz >>>>>>> markeri yonida, SHA va xabari bilan ko'rsatiladi.
5. --skip va avtomatik tashlab ketish
5.1 Commit allaqachon main da bo'lsa
fix/choy-narxi branch'ida ikki commit bor: choy narxi 6 000 va non narxi. Shu orada kimdir main da aynan o'sha choy o'zgarishini alohida commit qildi ("Menyu: choy narxini yangila"). Rebase:
git rebase mainwarning: skipped previously applied commit a17aaa9
hint: use --reapply-cherry-picks to include skipped commits
hint: Disable this message with "git config set advice.skippedCherryPicks false"
Successfully rebased and updated refs/heads/fix/choy-narxi.Tarjimasi: "ogohlantirish: oldin qo'llangan a17aaa9 commiti o'tkazib yuborildi". Git branch'dagi choy commitining o'zgarishi main da bor ekanini sezdi va uni takrorlamadi. Natijada branch'da faqat non narxi qoldi:
* 0be6fbb (HEAD -> fix/choy-narxi) Menyu: non narxini qo'sh
* 100e51b (main) Menyu: choy narxini yangilaXabarlar boshqa bo'lsa ham, Git o'zgarishning mazmunini solishtiradi.
5.2 --skip — o'zingiz tashlab ketish
Ba'zan conflict chiqadi, siz esa tushunasiz: bu commit endi kerak emas. Masalan, branch'da non narxi 5 000, main da esa allaqachon 4 500 qilingan — va to'g'risi main dagisi. Conflict'da:
git rebase --skipSuccessfully rebased and updated refs/heads/fix/non-narxi.Conflictli commit butunlay tashlandi — go'yo u hech qachon bo'lmagandek. Bizda branch'da boshqa commit yo'q edi, shuning uchun branch main bilan tenglashdi. --skip — o'sha commitdagi hamma o'zgarishdan voz kechish, shuning uchun uni o'ylab ishlating.
6. Oltin qoida
6.1 Qoida
Diqqat: Boshqalar ham ishlatayotgan branch'ni rebase qilmang. Ya'ni GitHub'ga yuborilgan va kimdir o'ziga olgan branch'ni — ayniqsa
mainni — hech qachon.
6.2 Nega?
«SHA'lar o'zgardi!» bo'limini eslang: rebase eski commitlarni tashlab, yangilarini yaratadi. Faqat sizning kompyuteringizda bo'lsa — hech kim zarar ko'rmaydi.
Endi tasavvur qiling: feature/ichimliklar GitHub'da turibdi va Rustam aka uni o'z kompyuteriga olib, ustiga commit qo'shdi. Siz esa branch'ni rebase qildingiz. Sizda — yangi 6761532, e666b2d. Rustam akada — eski df4ac38, afcf200 va uning commiti.
flowchart TB
subgraph S["Sizda (rebase'dan keyin)"]
A1["37c92ec"] --> A2["6761532"] --> A3["e666b2d"]
end
subgraph R["Rustam akada"]
B1["7658a99"] --> B2["df4ac38"] --> B3["afcf200"] --> B4["Rustamning commiti"]
endNimaga qarang: bir xil ish, ikki xil tarix. Git uchun df4ac38 va 6761532 — butunlay boshqa commitlar. Ikki tarix birlashganda o'sha o'zgarishlar ikki nusxada paydo bo'ladi, conflictlar ko'payadi, jamoa soatlab chalkashlikni tozalaydi.
Buni bitta kompyuterda ham ko'rsa bo'ladi. sinov-git/oltin repoda feature/salatlar branch'ini "Rustam oldi" — biz uning nusxasini rustam nomli branch qilib qo'ydik va ustiga commit qo'shdik. Keyin feature/salatlar ni main ustiga rebase qildik, ikkalasini main ga birlashtirdik:
git log --oneline22e1e7a (HEAD -> main) Merge branch 'rustam'
306bb27 (feature/salatlar) Menyu: olivye qo'sh
69e8af9 Menyu: achchiq-chuchuk qo'sh
7d06ace Manzil: faylni qo'sh
8df60e3 (rustam) Narxlar: faylni qo'sh
d04313d Menyu: olivye qo'sh
f335f5d Menyu: achchiq-chuchuk qo'sh
ae14b80 Menyu: faylni yarat"Olivye" va "achchiq-chuchuk" commitlari tarixda ikki marta turibdi: yangi SHA bilan (306bb27, 69e8af9) va eski SHA bilan (d04313d, f335f5d). Fayl mazmuni to'g'ri chiqdi, lekin tarix chalkashdi. Haqiqiy loyihada bunday dublikatlar conflictlarga va "bu commit qaysi?" degan savollarga olib keladi.
GitHub'ga yuborish va boshqalardan olish (Remote darsi) hali o'tilmagan. Hozircha oddiy qoida yetadi: rebase — faqat o'zingizning, hali hech kimga bermagan commitlaringiz uchun. O'z branch'ingizni GitHub'ga yuborgandan keyin rebase qilish kerak bo'lsa, maxsus xavfsiz buyruq bor (git push --force-with-lease) — uni Ajralgan tarix darsida o'rganamiz.
7. Merge yoki rebase?
Ikkalasi ham bitta vazifani bajaradi — ikki chiziqdagi ishni birlashtiradi. Farqi tarixda:
| Merge | Rebase | |
|---|---|---|
| Tarix shakli | Haqiqiy: ayrilish va qo'shilish ko'rinadi | Tekis chiziq, "go'yo ketma-ket" |
| Yangi commitlar | Bitta merge commit | Hamma commitlar qayta yaratiladi |
| Mavjud SHA'lar | O'zgarmaydi | O'zgaradi |
| Conflict | Bir marta, hammasi birga | Har commit uchun alohida |
| Vaziyat | Tavsiya |
|---|---|
O'z branch'ingizni main dagi yangiliklar bilan yangilash |
Rebase |
Tayyor ishni main ga qo'shish |
Merge (yoki rebase + fast-forward) |
Umumiy branch (main, boshqalar olgan branch) |
Faqat merge |
| Nima qilishni bilmasangiz | Merge — u hech narsani qayta yozmaydi |
Jamoalar o'z qoidasini tanlaydi. Ba'zilari tarix "haqiqiy" bo'lishini afzal ko'radi va faqat merge qiladi. Boshqalari tekis tarixni yaxshi ko'radi va har PR'dan oldin rebase talab qiladi. PR (pull request) — GitHub'da "branch'imni main ga qo'shing" degan so'rov; uni Pull Request darsida o'rganamiz. Ikkala yo'l ham to'g'ri — muhimi, oltin qoida buzilmasin.
8. git pull --rebase — kelajakka qisqa ko'prik
GitHub bilan ishlashni boshlaganingizda, git pull buyrug'i serverdagi yangiliklarni olib, sizning lokal ishingiz bilan birlashtiradi (Remote darsida). Standart holatda u merge qiladi va har safar "Merge branch 'main' of github.com/..." degan keraksiz commit yaratishi mumkin.
git pull --rebase esa birlashtirishni rebase bilan qiladi: sizning hali yuborilmagan commitlaringiz serverdagi yangiliklar ustiga qayta teriladi. Bu oltin qoidaga zid emas — qayta yoziladigan commitlar faqat sizda, hali hech kimga berilmagan. Ko'p dasturchilar buni doimiy qilib qo'yadi: git config --global pull.rebase true. Hozir sozlamang — bu mavzuni Ajralgan tarix darsida to'liq ko'ramiz.
9. Ko'p uchraydigan xatolar
9.1 Iflos ishchi papka
Commit qilinmagan o'zgarish bor paytda rebase boshlab bo'lmaydi:
git rebase main
git status -serror: cannot rebase: You have unstaged changes.
error: Please commit or stash them.
M b.txtTarjimasi: "rebase qilib bo'lmaydi: sizda staging'ga qo'shilmagan o'zgarishlar bor. Ularni commit yoki stash qiling".
Git ishingizni himoya qildi. Tuzatish: commit qiling yoki git restore bilan qaytaring (Stash darsida uchinchi yo'lni ko'rasiz).
9.2 add qilmay --continue
Conflictli faylni tahrirlab, git add ni unutsangiz:
menyu/index.html: needs merge
You must edit all merge conflicts and then
mark them as resolved using git add"menyu/index.html: birlashtirish kerak. Barcha merge ziddiyatlarini tahrirlab, keyin git add bilan hal qilingan deb belgilashingiz kerak". Fayl tahrirlangan bo'lsa ham, Git git add qilinmaguncha uni hal qilinmagan deb hisoblaydi. Tuzatish: git add <fayl>, keyin yana git rebase --continue.
9.3 Rebase yo'q paytda --continue
git rebase --continuefatal: no rebase in progress"Hech qanday rebase ketmayapti" — rebase allaqachon tugagan yoki --abort qilingan. Hech narsa qilish shart emas: git status bilan holatni tekshiring.
9.4 Noto'g'ri yo'nalish
main da turib git rebase feature/x yozish — main ning commitlarini feature ustiga ko'chirish demak. Bu oltin qoidani buzadi. Qoida: rebase o'z branch'ingizda turib, main nomi bilan: git switch feature/x, keyin git rebase main. Yoki bitta buyruq bilan: git rebase main feature/x — Git avval feature/x ga o'tadi, keyin uni main ustiga ko'chiradi.
9.5 Rebase'dan keyin "commitlarim yo'qoldi"
Aslida yo'qolmagan — ular yangi SHA bilan yangi joyda. Tekshirish: git log --oneline --graph --all. Natija yoqmasa — darhol git reset --hard ORIG_HEAD.
10. Mashqlar
1-mashq (oson): Rostmi yoki yolg'on?
git rebase maindan keyin branch'dagi commitlarning SHA'lari o'zgarmaydi.- Rebase'dan keyin
mainga merge odatda fast-forward bo'ladi. - Rebase paytidagi conflict'da
<<<<<<< HEADostida sizning commitingiz turadi. - GitHub'ga yuborilgan, hamkasbingiz olgan branch'ni rebase qilish xavfsiz.
Yechim
- Yolg'on — rebase yangi commitlar yaratadi, ota commit o'zgargani uchun SHA ham o'zgaradi.
- Rost — branch
mainuchining to'g'ridan-to'g'ri davomi bo'lib qoladi. - Yolg'on —
HEADrebase paytida yangi asos (main) tomoni; sizning commitingiz>>>>>>>yonida. - Yolg'on — bu oltin qoidani buzadi: hamkasbingizda eski commitlar qoladi va tarix ikkiga bo'linadi.
2-mashq (o'rta): Bo'sh joylarni to'ldiring
Rebase paytida conflict chiqdi. Yechish ketma-ketligi:
git rebase main
# CONFLICT (content): Merge conflict in menyu/index.html
git status
# VS Code'da markerlarni olib tashlaymiz
git menyu/index.html
git rebase Rebase'dan butunlay voz kechish uchun: git rebase . Bitta conflictli commitni tashlab ketish uchun: git rebase .
Ishora: «Rebase paytida conflict» bo'limidagi hint: qatorlari to'rtala buyruqni ham aytadi.
Yechim
git add menyu/index.html
git rebase --continueVoz kechish — --abort (hammasi rebase'dan oldingi holatga qaytadi), tashlab ketish — --skip (faqat joriy commit tashlanadi, qolganlari davom etadi). git commit yozilmaydi — rebase commitni o'zi yaratadi.
3-mashq (qiyin): Ikki argumentli rebase
Mashq mashqlar reposida, 07/18-rebase/ papkasida bo'ladi. Har echo dan keyin git add . va git commit -m "07/18: <harf>" qiling:
cd ~/kurs/mashqlar
mkdir -p 07/18-rebase
cd 07/18-rebase
echo A > a.txt # commit "07/18: A"
git switch -c feature/harflar
echo B > b.txt # commit "07/18: B"
echo C > c.txt # commit "07/18: C"
git switch main
echo D > d.txt # commit "07/18: D"git log --oneline --graph --all -4ni chizing — qayerda ayrilish?mainda turgan holda bitta buyruq bilanfeature/harflarnimainustiga ko'chiring.- Buyruqdan keyin qaysi branch'dasiz?
BvaCning SHA'lari o'zgardimi? mainga qaytib, branch'ni fast-forward bilan qo'shing va o'chiring.
Ishora: «Noto'g'ri yo'nalish» xatosidagi ikki argumentli shakl.
Yechim
Biz aynan shu buyruqlarni bajardik. Rebase'dan oldin:
* 968b904 (HEAD -> main) 07/18: D
| * e6317a2 (feature/harflar) 07/18: C
| * 09eae02 07/18: B
|/
* 2eac35b 07/18: ABuyruq va natija:
git rebase main feature/harflar
git branch
git log --oneline --graph --all -4Successfully rebased and updated refs/heads/feature/harflar.
* feature/harflar
main
* 82057e4 (HEAD -> feature/harflar) 07/18: C
* c141db5 07/18: B
* 968b904 (main) 07/18: D
* 2eac35b 07/18: ASiz endi feature/harflar dasiz — ikki argumentli rebase avval shu branch'ga o'tadi. B (09eae02 → c141db5) va C (e6317a2 → 82057e4) yangi SHA oldi, chunki ularning asosi A dan D ga ko'chdi. Sizda SHA'lar boshqacha bo'ladi, lekin o'zgarish fakti bir xil.
4-qadam:
git switch main
git merge feature/harflar
git branch -d feature/harflarSwitched to branch 'main'
Updating 968b904..82057e4
Fast-forward
07/18-rebase/b.txt | 1 +
07/18-rebase/c.txt | 1 +
2 files changed, 2 insertions(+)
create mode 100644 07/18-rebase/b.txt
create mode 100644 07/18-rebase/c.txt
Deleted branch feature/harflar (was 82057e4).Fast-forward — rebase'dan keyin merge commit kerak bo'lmadi.
4-mashq: Portfolio qadami — branch'ni yangilab qo'shish
Portfolio'da "Loyihalar" sahifasiga landing'ingizga havola qo'shamiz. Shu orada main da boshqa kichik ish bajariladi — va branch'ni rebase bilan yangilaymiz.
feature/landing-havolabranch'ini oching.sayt/loyihalar/index.htmlga landing havolasini qo'shing (masalan,<a href="/landing/">Landing: Bahor</a>). Commit:Loyihalar: landing havolasini qo'sh.mainga qayting vasayt/404.htmlga tushuntiruvchi jumla qo'shing. Commit:404: tushuntirish matnini qo'sh.feature/landing-havolaga o'tib,git rebase main.mainga qaytib, merge qiling — fast-forward bo'lishi kerak. Branch'ni o'chiring.git log --oneline -4bilan tekshiring: merge commit yo'q, tarix tekis.
Yechim
cd ~/kurs/portfolio
git switch -c feature/landing-havola
# loyihalar sahifasiga havola
git commit -am "Loyihalar: landing havolasini qo'sh"
git switch main
# 404 sahifasiga jumla
git commit -am "404: tushuntirish matnini qo'sh"
git switch feature/landing-havola
git rebase main
git switch main
git merge feature/landing-havola
git branch -d feature/landing-havola
git log --oneline -4Qisqa sinov portfolio'sida rebase'dan oldin va keyin:
* cbc0687 (main) 404: tushuntirish matnini qo'sh
| * 01567ef (HEAD -> feature/landing-havola) Loyihalar: landing havolasini qo'sh
|/
* 868a51c Merge branch 'feature/footer-ism'
...
* b61fb7a (HEAD -> feature/landing-havola) Loyihalar: landing havolasini qo'sh
* cbc0687 (main) 404: tushuntirish matnini qo'sh
* 868a51c Merge branch 'feature/footer-ism'
...Merge va oxirgi tarix:
Updating cbc0687..b61fb7a
Fast-forward
sayt/loyihalar/index.html | 1 +
1 file changed, 1 insertion(+)
b61fb7a (HEAD -> main) Loyihalar: landing havolasini qo'sh
cbc0687 404: tushuntirish matnini qo'sh
868a51c Merge branch 'feature/footer-ism'
dfcc3ec Footer: shaharni qo'shHavola commiti SHA'sini o'zgartirdi (01567ef → b61fb7a) — bu normal, branch hali hech kimga berilmagan edi. Portfolio hali GitHub'ga ulanmagan, shuning uchun oltin qoida bu yerda buzilmaydi.
11. Real ishda
- "Rebase qilib yuboring". PR'ingiz eskirib qolsa, reviewer ko'pincha shunday so'raydi: branch'ingizni yangi
mainustiga olib keling. Bu aynangit rebase main(keyin xavfsiz push — Ajralgan tarix). - GitHub'dagi "Rebase and merge" tugmasi PR commitlarini
mainustiga rebase qilib qo'shadi (Pull Request). - Tekis tarix
git log, blame va xatoni topishni osonlashtiradi — shuning uchun ko'p jamoalar rebase'ni afzal ko'radi. - Intervyuda klassik savol: "Merge va rebase farqi nima? Qachon rebase qilmaysiz?" Kuchli javob — SHA qayta yozilishi va oltin qoida.
Xulosa
git rebase mainjoriy branch commitlarinimainuchiga qayta qo'yadi — tarix tekis, keyingi merge fast-forward.- Rebase yangi commitlar yaratadi: ota o'zgargani uchun SHA'lar o'zgaradi; eski uch
ORIG_HEADda. - Conflict'da: yechish →
git add→git rebase --continue; qochish —--abort; commitni tashlash —--skip. - Rebase paytida
HEAD—maintomoni, sizning commitingiz>>>>>>>yonida. - Oltin qoida: umumiy, boshqalar olgan branch'ni rebase qilmang; bilmasangiz — merge.
Keyingi dars: Interaktiv rebase: PR'dan oldin tarixni tozalash — rebase'ning pick ro'yxatini o'zingiz tahrirlab, chalkash commitlarni birlashtirish, qayta nomlash va o'chirishni o'rganamiz.
Manbalar
- Pro Git kitobi: "Git Branching — Rebasing" (ayniqsa "The Perils of Rebasing") — git-scm.com/book
- Git hujjati: "git-rebase", "git-pull" (
--rebase) — git-scm.com/docs
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!