Mundarija (39)
- Bu darsda
- 1. Nega bu kerak?
- 2. PR hajmi
- 2.1 Kanon o'lchovi
- 2.2 Biz shunday xato qildik
- 2.3 Hajmni o'lchash
- 2.4 Qanday bo'lish
- 3. Sarlavha
- 4. Tavsif: PR shabloni
- 4.1 Kanon shabloni
- 4.2 Har bo'lim nega bor
- 4.3 Yaxshi tavsif namunasi
- 4.4 Biz shunday xato qildik: shablon bor, lekin ishlatilmadi
- 4.5 Skrinshot va "qo'lda" bandi
- 5. Self-review: reviewer'dan oldin o'zingiz
- 5.1 Nima uchun
- 5.2 To'rt buyruq
- 5.3 Self-review ro'yxati
- 6. Draft PR
- 7. Stacked PR'lar
- 7.1 Muammo
- 7.2 Base — eng muhim tanlov
- 7.3 Pastki PR o'zgarsa
- 7.4 Pastki PR squash bilan merge bo'lsa — tuzoq
- 8. PR hayoti: hammasi birga
- 9. Loyiha qadami: PR shabloni va CONTRIBUTING.md
- 10. Ko'p uchraydigan xatolar
- 10.1 "Yo'l-yo'lakay" o'zgarishlar
- 10.2 Shablonni o'chirib tashlash
- 10.3 Noto'g'ri base
- 10.4 Squash'dan keyin rebase main konflikti
- 10.5 CI qizil, lekin "review qilib turing"
- 11. Mashqlar
- 1-mashq (oson): bo'shliqlarni to'ldiring
- 2-mashq (o'rta): tavsif tekshiruvchisi
- 3-mashq (qiyin): stack'ni qutqarish
- 12. Real ishda
- Xulosa
- Manbalar
Yaxshi PR tayyorlash: hajm, sarlavha, PR shabloni va self-review
Qisqacha: Yaxshi PR — reviewer uni tez va to'liq tushunadigan PR. Uch narsa hal qiladi. Hajm — kichik bo'lsin, taxminan 200–400 qatordan kam: katta PR yuzaki ko'rib chiqiladi. Sarlavha — Conventional Commits shaklida, chunki squash'dan keyin u
maindagi commit xabariga aylanadi. Tavsif — PR shabloni bo'yicha: nima o'zgardi, nega, qanday tekshirildi, nimaga diqqat qilish kerak, xavf va qaytarish yo'li. Reviewer'ni chaqirishdan oldin o'z diff'ingizni o'zingiz ko'rib chiqasiz (self-review). Kanon sinov reposidagi eng katta PR +457/−54 qator edi — bitta PR'da 7 ta tuzatish; shu darsda uning narxini ko'ramiz.
Bu darsda
- PR hajmini o'lchaysiz va katta ishni bir nechta PR'ga bo'lasiz.
- Squash'dan keyin tarixda qoladigan sarlavha yozasiz.
vazifalar-apiuchun PR shablonini yaratasiz va uning har bo'limini tushuntirasiz.git diff --stat,--checkvamain..HEADbilan self-review qilasiz.- Draft PR va stacked PR'larni qachon ishlatishni, squash'dan keyingi
rebase --ontoni bilasiz.
Oldin bilishingiz kerak: Pull Request: yaratish, muhokama, merge, Issues, Projects va shablonlar, Interaktiv rebase, Jamoa workflow'lari, Jamoadagi yangi loyihaga kirish.
1. Nega bu kerak?
Reviewer o'rniga o'zingizni qo'ying. Ertalab sizga ikki PR keldi. Birinchisi — 40 qator, sarlavhasi fix(bron): vaqtsiz bron rad etiladi, tavsifda "nega" va "qanday tekshirdim". Siz uni 10 daqiqada o'qib, bitta aniq savol berasiz. Ikkinchisi — 19 fayl, 500 qator, sarlavhasi "tuzatishlar", tavsif bo'sh. Uni qachon ochasiz? Ehtimol, tushdan keyin. Va ehtimol, yuzaki ko'rib, "LGTM" ("menga yaxshi ko'rinadi") deysiz.
Katta PR'lar sekin merge bo'ladi va yomonroq tekshiriladi. Google'ning ochiq review qo'llanmasida ham asosiy maslahat shu: o'zgarishlarni kichik qiling — ular tezroq va sinchiklab ko'rib chiqiladi, qaytarish osonroq. Qo'llanmadagi mo'ljal: ~100 qator odatda maqbul, ~1 000 — odatda juda katta (google.github.io/eng-practices, 2026-11).
Pull Request darsida PR ochishni o'rgangansiz. Endi — PR'ni reviewer uchun tayyorlash. Hayotiy o'xshatish: pochta posilkasi. Ichida nima borligi yozilgan, sinadigan narsa alohida o'ralgan, katta yuk bir nechta qutiga bo'lingan bo'lsa — qabul qiluvchi tez tekshiradi.
2. PR hajmi
2.1 Kanon o'lchovi
Kurs sinov reposidagi PR'lar hajmi (qo'shilgan + o'chirilgan qatorlar, GitHub API'dan gh pr list bilan olindi):
- #9 31 nuqsonlari511 qator
- #17 shablonlar, ADR230 qator
- #15 README159 qator
- #14 CONTRIBUTING102 qator
- #13 arxitektura101 qator
- #12 CODEOWNERS34 qator
- #20 sayt README8 qator
Manba: Kurs sinov reposi (github.com/Sarvarbek0704/ilmhamroh-git-sinov), gh pr list --json additions,deletions, 2026-11-04
Birinchi ustun boshqalardan ancha baland. PR #9 — 19 fayl, +457/−54. Uning tavsifida yettita raqamlangan band bor: circuit breaker, deadline, DEFAULT bo'lim, embedding prefiksi, oqim kvotasi, audit, MCP annotatsiyasi.
2.2 Biz shunday xato qildik
PR #9 da yettita mustaqil tuzatish bitta PR'ga tushdi. Oqibatlari:
- Review'da diqqat taqsimlandi. Kanon review'idagi to'rtta qator izohi breaker, deadline, token taxmini va migratsiya qulfiga tushdi. Qolgan uch tuzatish (embedding prefiksi, audit, MCP) birorta ham izoh olmadi. Ular xatosiz bo'lishi mumkin — lekin katta PR'da reviewer diqqati aynan shunday bo'linadi.
- Tarix yo'qoldi. Squash'dan keyin
mainda yettita tuzatish bitta commit:22a1226. Agar audit tuzatishi xato bo'lib chiqsa, uni alohidagit revertqilib bo'lmaydi — breaker ham qaytadi. - Bisect qo'pollashdi. Bisect bu commitni "aybdor" deb topsa, yetti tuzatishdan qaysi biri ekanini baribir qo'lda qidirasiz.
To'g'ri yo'l — kamida uchta PR: breaker va deadline (bir-biriga bog'liq, AI chidamliligi); DEFAULT bo'lim (migratsiya — alohida ehtiyot bilan ko'riladi); qolgan mayda tuzatishlar. Kanonni o'zgartirmadik — xato misol sifatida qoladi.
2.3 Hajmni o'lchash
Hajmni PR ochishdan oldin terminalda ko'rasiz:
git diff --shortstat main...HEADmain...HEAD (uchta nuqta) — branch main dan ajralgan nuqtadan beri sizning o'zgarishlaringiz. Biz shu buyruq chiqishini baholaydigan kichik funksiya yozdik. Chegaralar — kanon CONTRIBUTING.md dan: ≈ 200–400 qator.
function prHajmi(stat) {
const qosh = Number(stat.match(/(\d+) insertion/)?.[1] ?? 0);
const ochir = Number(stat.match(/(\d+) deletion/)?.[1] ?? 0);
const jami = qosh + ochir;
if (jami <= 200) return `${jami} qator — kichik`;
if (jami <= 400) return `${jami} qator — o'rta`;
return `${jami} qator — katta, bo'ling`;
}
console.log(prHajmi(" 4 files changed, 102 insertions(+)"));
console.log(prHajmi(
" 4 files changed, 89 insertions(+), 70 deletions(-)"));
console.log(prHajmi(
" 19 files changed, 457 insertions(+), 54 deletions(-)"));
console.log(prHajmi(" 1 file changed, 1 deletion(-)"));Konsolda:
102 qator — kichik
159 qator — kichik
511 qator — katta, bo'ling
1 qator — kichikKirishlar — kanon PR #14, #15 va #9 ning haqiqiy raqamlari, --shortstat ko'rinishida. match va ?.[1] — RegExp asoslari darsidan: guruh topilmasa null, ?. xato bermaydi, ?? 0 — nol. Bitta qator ham — normal PR: imlo tuzatishi.
Raqam — qoida emas, ishora: 600 qatorlik package-lock.json review'ni og'irlashtirmaydi, 80 qatorlik xavfsizlik o'zgarishi esa sinchkov ko'riladi.
2.4 Qanday bo'lish
Katta ishni ikki xil bo'lish mumkin:
- Qatlam bo'yicha: 1) migratsiya va ombor, 2) xizmat va testlar, 3) controller va hujjat. Har PR o'zi ishlaydi: migratsiya qo'shildi, lekin hali hech kim ishlatmaydi. Kanon
CONTRIBUTING.mdda aynan shu misol. - Mavzu bo'yicha: bir-biriga bog'liq bo'lmagan o'zgarishlar — alohida PR. PR #9 shunday bo'linishi kerak edi.
Kanonda yaxshi misol ham bor. README va hujjatlar ishi ikkiga bo'lindi: PR #14 — CONTRIBUTING, SECURITY va PR shabloni (+102); PR #15 — README qayta tuzildi va eski bo'limlar docs/qanday/ ga ko'chirildi (+89/−70). Sarlavhalarda (1/2) va (2/2) — reviewer ikkinchisi borligini biladi. PR #15 tavsifida "Review uchun" bo'limi: "Faqat ko'chirilgan bloklar: docs/qanday/*.md — eski README'dan aynan". Reviewer 48 qatorni so'zma-so'z o'qimaydi — faqat aynan ko'chirilganini tekshiradi.
Yana bir qoida: ko'chirish va o'zgartirishni aralashtirmang. Faylni boshqa papkaga ko'chirib, ichini ham tahrirlasangiz, diff'da hammasi "yangi" ko'rinadi. Avval ko'chirish (alohida commit yoki PR), keyin tahrir.
Tekshirib ko'ring: Siz
vazifalarjadvaliga yangi ustun qo'shdingiz: migratsiya, Prisma sxemasi, servis, controller, testlar va OpenAPI surati — jami 620 qator. Qanday bo'lasiz?
Javob
Qatlam bo'yicha, har biri o'zi ishlaydigan qilib. 1-PR: migratsiya va sxema — ustun qo'shiladi, hech kim ishlatmaydi (Zero-downtime: expand-contract darsidagi "expand" qadami). 2-PR: servis va uning testlari. 3-PR: controller, OpenAPI surati va hujjat. Har biri 150–250 qator, har birini alohida qaytarish mumkin. Migratsiya alohida bo'lgani yaxshi: u eng xavfli qism va eng sinchkov review'ni talab qiladi.
3. Sarlavha
GitHub flow'da merge — squash (Jamoa workflow'lari). Squash commitining xabari — PR sarlavhasi va oxirida PR raqami. Kanon main tarixidan:
0ae90b7 docs: README qayta tuzildi, qo'llanmalar docs/qanday ga (2/2) (#15)
8fff1c5 docs: CONTRIBUTING, SECURITY va PR shabloni (1/2) (#14)
29d20db docs: arxitektura xaritasi va birinchi vazifa yo'riqnomasi (#13)Demak sarlavha — PR yopilgandan keyin ham yashaydigan yagona matn. Conventional Commits shaklida bo'lsa, CHANGELOG vositalari uni o'qiydi.
-
Tuzatishlar— nimani? qayerda? -
Review izohlarini tuzatdim— PR ichidagi commit uchun mos, PR uchun emas. -
feat: README, CONTRIBUTING, breaker va audit— bitta sarlavhada to'rt mavzu = to'rtta PR. -
fix(bron): vaqtsiz bron rad etiladi— tur, qamrov, natija. -
docs: CONTRIBUTING, SECURITY va PR shabloni (1/2)— seriyaning qismi ekani ko'rinadi.
Sarlavhaga "va" qo'shilsa — to'xtab o'ylang: balki bu ikki PR?
4. Tavsif: PR shabloni
4.1 Kanon shabloni
Issues va shablonlar darsida «Bahor» sayti uchun oddiy shablon yozgansiz. vazifalar-api — backend, unda xavf boshqacha: migratsiya, muhit o'zgaruvchisi, API shartnomasi. Kanon shabloni .github/pull_request_template.md (aynan; uzun izoh qatorlari telefon uchun bo'lindi):
## Nima o'zgardi
<!-- 1–3 gap: nima qilindi. Sarlavha — conventional commit
shaklida: `fix(ai): …`, `feat: …`, `docs: …` -->
## Nega
<!-- Muammo yoki issue: `Closes #12` (merge bo'lganda issue
avtomatik yopiladi). Muqobil yo'llar bo'lsa — nega aynan shu. -->
## Qanday tekshirildi
- [ ] `npm run check` yashil (tip, lint, test, build)
- [ ] yangi/o'zgargan xulq uchun test bor (xato tuzatilgan
bo'lsa — avval yiqiladigan regressiya testi)
- [ ] qo'lda: <!-- qaysi so'rov, qaysi natija
(curl chiqishi, skrinshot) -->
## Review uchun
<!-- Qayerga diqqat qilish kerak, nima ataylab qilinmagan,
qaysi fayllar faqat ko'chirilgan. Katta PR bo'lsa — nega
bo'linmadi. -->
## Xavf va qaytarish
- [ ] migratsiya yo'q / bor (orqaga qaytarish yo'li: …)
- [ ] yangi muhit o'zgaruvchisi yo'q / bor
(`.env.example` yangilandi)
- [ ] API shartnomasi o'zgarmadi / o'zgardi
(`docs/openapi-snapshot.json`, mijozlarga ta'siri: …)<!-- … --> — HTML izoh: PR sahifasida ko'rinmaydi, faqat yozayotganda maslahat beradi. Muallif uni o'z matni bilan almashtiradi.
4.2 Har bo'lim nega bor
| Bo'lim | Kim uchun | Qaysi savolga javob |
|---|---|---|
| Nima o'zgardi | reviewer | "nimani kutib o'qiyman?" |
| Nega | reviewer, kelajakdagi o'quvchi | "bu muammo haqiqiymi, yechim to'g'rimi?" |
| Qanday tekshirildi | reviewer | "nimani qayta tekshirmasam bo'ladi?" |
| Review uchun | reviewer | "qayerga diqqat qilay?" |
| Xavf va qaytarish | deploy qiluvchi | "nima buzilishi mumkin, qanday ortga qaytaramiz?" |
"Nega" — eng muhimi. Kod nima qilishini ko'rsatadi, lekin nega degan savolga javob bermaydi. Bir yildan keyin kimdir Kod arxeologiyasi usuli bilan qatorga yetib keladi, commitdan PR'ga o'tadi va sababni shu yerdan o'qiydi.
"Xavf va qaytarish" — backend'ga xos. Migratsiya bor PR'ni qaytarish oddiy git revert dan murakkab: baza allaqachon o'zgargan. Shuning uchun qaytarish yo'li oldindan yoziladi.
4.3 Yaxshi tavsif namunasi
Kanon PR #9 — katta, lekin tavsifi namunali. Undan ikki bo'lim (aynan):
## Nega
Breaker nuqsonini kiritgan commit `git bisect run` bilan topildi:
7 nomzoddan 3 qadamda — chidamlilik qo'shilgan commit (31-qism #29).
Qolganlari — 31-qism review'ida topilgan ochiq xatolar.
## Xavf va qaytarish
- [x] migratsiya bor: faqat funksiya almashtiriladi
(`CREATE OR REPLACE`), qaytarish — 301 dagi eski ta'rif
- [x] yangi muhit o'zgaruvchisi: `AI_DEADLINE_MS` (ixtiyoriy,
`.env.example` da)
- [x] API shartnomasi o'zgarmadi (OpenAPI surati testi o'tdi)"Nega" da dalil bor: xato qanday topilgani. "Xavf" da har band aniq: migratsiya qanday qaytariladi, yangi o'zgaruvchi majburiy emas. Deploy qiluvchi kodni o'qimasdan qarorni shu yerdan oladi.
4.4 Biz shunday xato qildik: shablon bor, lekin ishlatilmadi
Shablon PR #14 bilan main ga tushdi. Keyingi to'rtta PR (#15, #17, #18, #19) tavsiflarini GitHub API'dan tekshirdik — hech birida "Xavf va qaytarish" bo'limi yo'q, faqat #15 da "Review uchun" bor.
Sabab — asbob. Kanon PR'larni gh pr create --body-file pr.md bilan ochdi: tavsif tayyor fayldan olindi, shablon esa umuman ochilmadi. Brauzerda "New pull request" bosilganda GitHub tavsif maydonini shablon bilan to'ldiradi (docs.github.com, sinalmagan, 2026-11). gh da esa shablonni o'zingiz berasiz: gh pr create --help ga ko'ra, -T, --template file — "boshlang'ich tavsif matni uchun shablon fayli".
Bu PR'larda faqat hujjat o'zgargan, xavf amalda nol. Lekin odat buzildi. Saboq: shablon faqat eslatadi, majburlamaydi. Majburlash kerak bo'lsa — CI'da tavsifni tekshiruvchi qadam (2-mashqdagi funksiya kabi) yoki review'da reviewer talabi.
4.5 Skrinshot va "qo'lda" bandi
UI o'zgarsa — tavsifga "oldin" va "keyin" skrinshotlari. Reviewer branch'ni yuklab, ishga tushirmasdan natijani ko'radi. Backend'da skrinshot o'rnini so'rov va javob egallaydi: curl buyrug'i va uning chiqishi, kodi bilan. Shablondagi "qo'lda:" bandi aynan shu uchun.
5. Self-review: reviewer'dan oldin o'zingiz
5.1 Nima uchun
Self-review — PR'ni boshqalarga ko'rsatishdan oldin o'z diff'ingizni reviewer ko'zi bilan o'qish. Unutilgan console.log, keraksiz fayl, yarim qolgan izoh — bularni o'zingiz topsangiz, reviewer vaqti muhim savollarga qoladi.
5.2 To'rt buyruq
Biz docs/hissa-qoshish branch'ida PR shabloni va CONTRIBUTING.md boshini qo'shib, tekshirdik:
git log --oneline main..HEAD
git diff --stat main...HEAD
git diff --check main...HEAD; echo "exit $?"f8ed0cc docs: CONTRIBUTING va PR shabloni (1/2)
.github/pull_request_template.md | 23 +++++++++++++++++++++++
CONTRIBUTING.md | 3 +++
2 files changed, 26 insertions(+)
CONTRIBUTING.md:3: trailing whitespace.
+Ish oqimi: GitHub flow.
exit 2git log --oneline main..HEAD— PR'ga qaysi commitlar kiradi. Begona commit ko'rinsa — branch noto'g'ri joydan ochilgan.git diff --stat main...HEAD— qaysi fayllar va qancha. Kutilmagan fayl (.env,dist/, rasm) — darhol ko'rinadi.git diff --check— bo'shliq xatolari. Bizda topdi: 3-qator oxirida ortiqcha bo'sh joy ("trailing whitespace"). Chiqish kodi 2 — skriptda ham ishlatsa bo'ladi. Tuzatgandan keyin — 0.git diff main...HEAD— to'liq diff. Uni boshidan oxirigacha o'qing, ayniqsa o'zingiz yozmagan joylarni: muharrir avtomatik o'zgartirgan import tartibi, formatlash.
Tarixni tartibga keltirish kerak bo'lsa ("tuzatdim", "yana tuzatdim") — Interaktiv rebase darsidagi --fixup va --autosquash. Squash merge'da bu main ga ta'sir qilmaydi, lekin reviewer PR ichidagi commitlarni o'qiydi.
5.3 Self-review ro'yxati
- Sarlavha Conventional Commits shaklida, bitta mavzu.
- Tavsifdagi hamma bo'lim to'ldirilgan,
Closes #…bor. npm run checkyashil — push'dan oldin, CI'dan emas.- Diff'da keraksiz fayl, debug kodi, sir (kalit, parol) yo'q.
- Yangi xulq uchun test bor; tuzatish uchun — avval yiqilgan test.
- PR ichida o'z kodingizga qatorlik izoh: "bu yerda nega bunday" — reviewer savolidan oldin.
6. Draft PR
Pull Request darsidan bilasiz: draft — "hali tayyor emas" belgisi, uni merge qilib bo'lmaydi. Lekin qachon ishlatish kerak?
- Yo'nalish so'rash. Ish yarmida "shu yo'l to'g'rimi?" deb so'ramoqchisiz. Draft ochib, savolni tavsifga yozasiz. Kanon
ARXITEKTURA.mddagi birinchi vazifa tartibi ham shuni aytadi: "Savol tug'ilsa — PR'ni draft qilib oching va so'rang." - CI'ni ko'rish. Lokal sinab bo'lmagan narsa (boshqa OS, boshqa Node versiyasi) — draft PR'da CI ishlaydi.
- Katta ishni ko'rinadigan qilish. Jamoa sizning ishingizni erta ko'radi va takrorlamaydi.
Terminalda: gh pr create --draft, tayyor bo'lgach — gh pr ready. Kanon PR'lari draft bo'lmadi: savol beradigan ikkinchi odam yo'q edi.
Draft — ruxsatnoma emas: ikki hafta draft'da yotgan PR — uzoq yashovchi branch'ning o'zi.
7. Stacked PR'lar
7.1 Muammo
Ikkinchi PR birinchisiga bog'liq. PR #15 (README) PR #14 dagi CONTRIBUTING.md ga havola qiladi. Birinchisi review'da kutyapti. Ikkinchisini kutib o'tirasizmi?
Stacked PR (qavatma-qavat PR'lar) — ikkinchi branch'ni birinchisining ustidan ochish. Kanonda #14 va #15 stack emas edi: #15 faqat #14 merge bo'lgach ochildi. Shuning uchun stack'ni biz lokal repoda sinadik.
gitGraph
commit id: "boshlang'ich"
branch docs/hissa-qoshish
commit id: "(1/2) CONTRIBUTING"
branch docs/readme
commit id: "(2/2) README"Diagrammada docs/readme main dan emas, docs/hissa-qoshish dan o'sgan.
7.2 Base — eng muhim tanlov
Ikkinchi PR'ni ochganda GitHub so'raydi: qaysi branch'ga? main ni tanlasangiz, reviewer ikki PR'ning hammasini ko'radi:
git diff --stat main...docs/readme
git diff --stat docs/hissa-qoshish...docs/readme .github/pull_request_template.md | 23 +++++++++++++++++++++++
CONTRIBUTING.md | 3 +++
README.md | 2 ++
3 files changed, 28 insertions(+)
README.md | 2 ++
1 file changed, 2 insertions(+)Birinchi — base main: uch fayl, birinchi PR ham ichida. Ikkinchi — base docs/hissa-qoshish: faqat README. Stack'da ikkinchi PR'ning base'i — birinchi PR'ning branch'i (gh pr create --base docs/hissa-qoshish).
7.3 Pastki PR o'zgarsa
Review'da birinchi PR'ga tuzatish so'raldi. Uni docs/hissa-qoshish ga qo'shasiz, keyin yuqori branch'ni yangilaysiz:
git switch docs/readme
git rebase docs/hissa-qoshishBu — oddiy rebase. Uch-to'rt qavatli stack uchun Git'da git rebase --update-refs bor: yuqori branch'ni rebase qilganda oradagi branch'larni ham suradi (Git hujjati, sinalmagan, 2026-11).
7.4 Pastki PR squash bilan merge bo'lsa — tuzoq
Eng nozik joy shu. Birinchi PR squash bilan main ga tushdi: main da yangi commit paydo bo'ldi, mazmuni pastki branch'ning hamma commitlari. Yuqori branch esa hali eski commitlar ustida. Oddiy git rebase main qilamiz:
CONFLICT (add/add): Merge conflict in CONTRIBUTING.md
error: could not apply b50d5b5... docs: CONTRIBUTING va PR shabloni (1/2)
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".Chiqish qisqartirildi. Git pastki PR'ning eski commitlarini main ustiga qayta qo'ymoqchi bo'ldi. Lekin ularning mazmuni main da allaqachon bor — boshqa SHA bilan, squash shaklida. Natija — o'z kodingiz bilan konflikt.
To'g'ri yo'l — --onto: "faqat pastki branch'dan keyingi commitlarni ko'chir":
git rebase --abort
git rebase --onto main docs/hissa-qoshish docs/readme
git log --oneline --graph main docs/readme* eb1daf6 docs: README qayta tuzildi (2/2)
* eee8a37 docs: CONTRIBUTING va PR shabloni (1/2) (#14)
* a8427cb feat: boshlang'ichgit rebase --onto <yangi-asos> <eski-asos> <branch> — <eski-asos> dan keyingi commitlarni <yangi-asos> ustiga ko'chiradi. Bizda faqat bitta README commiti ko'chdi, konfliktsiz. Endi ikkinchi PR'ning base'ini GitHub'da main ga almashtirasiz — farq yana faqat README.
Tekshirib ko'ring: Nega squash'dan keyin oddiy
git rebase mainkonflikt berdi, lekin merge commit bilan qo'shilganda bunday bo'lmasdi?
Javob
Merge commit pastki branch'ning o'sha commitlarini (o'sha SHA bilan) main tarixiga qo'shadi. Rebase ularni "allaqachon bor" deb taniydi va o'tkazib yuboradi. Squash esa yangi commit yaratadi — SHA boshqa. Git eski commitlarni tanimaydi va ularni yana qo'ymoqchi bo'ladi. Shuning uchun squash ishlatiladigan repoda stack'ning yuqori qavati doim --onto bilan ko'chiriladi. Pastki PR merge bo'lib, branch'i o'chirilsa, GitHub yuqori PR'ning base'ini o'zi main ga almashtiradi (hujjatga ko'ra, 2026-11; sinalmagan). Commitlarni ko'chirish esa baribir sizda.
Stack — kuchli, lekin qimmat usul. Ikki qavatdan ortiq stack'ni qo'lda yuritish qiyin; katta jamoalar buning uchun maxsus vositalardan foydalanadi (sinalmagan). Boshlang'ich qoida: avval PR'ni kichik qiling va tez merge qildiring — shunda stack kamdan-kam kerak bo'ladi.
8. PR hayoti: hammasi birga
flowchart LR
A["branch + commit"] --> B["self-review:<br/>log, stat, check"]
B --> C{"tayyormi?"}
C -->|yo'q| D["draft PR:<br/>savol"]
D --> B
C -->|ha| E["PR: sarlavha<br/>+ shablon"]
E --> F["review"]
F -->|izohlar| B
F -->|tasdiq| G["squash merge"]Diagrammaga qarang: self-review bir marta emas — har review aylanishidan keyin yana. Review — keyingi darsning mavzusi: Code review berish va olish.
9. Loyiha qadami: PR shabloni va CONTRIBUTING.md
Endi vazifalar-api ga ikki fayl qo'shasiz. Branch — docs/hissa-qoshish. Uni Jamoa workflow'lari darsida ochgan bo'lsangiz, u eski main dan o'sgan: keyingi CODEOWNERS va arxitektura commitlari unda yo'q. Shuning uchun -c emas, -C (katta harf):
git switch main
git pull
git switch -C docs/hissa-qoshish
mkdir -p .github-c bor branch'da xato beradi — biz sinadik: fatal: a branch named 'docs/hissa-qoshish' already exists. -C esa branch bo'lmasa yaratadi, bor bo'lsa uni hozirgi main ga qayta qo'yadi (Switched to and reset branch). Bu branch'da hali commit yo'q, shuning uchun hech narsa yo'qolmaydi.
.github/pull_request_template.md— «Kanon shabloni» bo'limidagi matn. GitHub uni repo ildizidagi.github/dan oladi. Kanon sinov reposi monorepo edi (07-qism portfoliosi vavazifalar-apiyonma-yon), shuning uchun shablon ikki joyga qo'yildi: ildizdagi.github/(GitHub o'qiydi) vavazifalar-api/.github/(loyiha alohida repo bo'lganda). Sizning repo'ngizdavazifalar-api— ildiz, bitta fayl yetadi.CONTRIBUTING.md— hozircha boshi va "Ish oqimi" bo'limi. Jamoa workflow'lari darsida va'da bergan edik: kelishuv hujjatda ham tursin. Kanon faylidan (aynan; telefon uchun qatorlar bo'lindi):
# Hissa qo'shish
Rahmat! Bu fayl — loyihaga o'zgarish kiritishning kelishilgan yo'li.
Qisqa bo'lishga harakat qildik: o'qish 5 daqiqa.
## Ish oqimi (GitHub flow)
1. **Issue** — katta ish oldidan issue oching yoki mavjudini oling
("men olaman" deb yozing). Kichik tuzatish (imlo, bitta qator) —
issue'siz ham bo'ladi.
2. **Branch** — `main` dan: `git switch -c <tur>/<qisqa-nom>`.
Tur — commit turi bilan bir xil: `feat/`, `fix/`, `docs/`,
`test/`, `refactor/`, `chore/`.
Misol: `fix/ai-deadline`, `docs/arxitektura`.
3. **Commit'lar** —
[Conventional Commits](https://www.conventionalcommits.org/):
`<tur>(<qamrov>): <nima>`. Qamrov — papka/modul: `ai`, `auth`,
`db`, `api`. Xabar — buyruq maylida, kichik harf, nuqtasiz,
≤ 72 belgi. Nega — tanada. Buzuvchi o'zgarish — `feat!:` yoki
tanada `BREAKING CHANGE:`.
CHANGELOG va versiya shu xabarlardan hosil qilinadi — shuning
uchun tur muhim (`fix` → patch, `feat` → minor, `!` → major).
4. **Tekshiruv** — `npm run check` (tip, lint, test, build).
Push'dan oldin. Qizil bo'lsa — PR ochmang (draft bundan mustasno).
5. **PR** — shablonni to'ldiring. Kichik bo'lsin: ≈ 200–400 qator
o'zgarish; kattasi — bir nechta ketma-ket PR'ga bo'linadi
(masalan: 1) migratsiya va ombor, 2) xizmat va testlar,
3) controller va hujjat).
6. **Review** — kamida bitta tasdiq. Izohlarga javob bering yoki
tuzating; "hal qilindi"ni izoh egasi bosadi. Merge — **squash**
(bitta PR = `main` da bitta commit).
7. Merge'dan keyin branch o'chiriladi.
`main` himoyalangan: to'g'ridan-to'g'ri push, force push va o'chirish
taqiqlangan — faqat PR orqali.Bu dars mavzusi — 5-band: hajm, shablon, bo'lish usuli. 6-band — review, uning madaniyati keyingi darsda shu faylga qo'shiladi. Kanon faylida yana "Kod uslubi" va "Xato haqida xabar berish" bo'limlari bor — ular va SECURITY.md Texnik yozish: README va loyiha hujjatlari darsida.
Diqqat: Hali commit qilmang. PR shabloni,
CONTRIBUTING.mdvaSECURITY.md— bitta mavzu ("hissa qo'shish hujjatlari"), ular Texnik yozish darsida birga commit qilinadi:docs: CONTRIBUTING, SECURITY va PR shabloni (1/2). Kanonda bu PR #14 — 4 fayl, +102 qator (monorepo'da shablon ikki joyda edi; sizda 3 fayl bo'ladi).
Hozir faqat self-review qiling: git status (ikki yangi fayl), keyin git add .github CONTRIBUTING.md va git diff --cached --check — chiqish kodi 0 bo'lsin. Nega --cached? Biz sinadik: yangi fayl uchun oddiy git diff --check jim o'tdi (exit 0) — u faqat ishchi papka bilan staging farqiga qaraydi. --cached esa staging'dagi bo'shliq xatosini topdi (exit 2).
10. Ko'p uchraydigan xatolar
10.1 "Yo'l-yo'lakay" o'zgarishlar
Xato tuzatib, yonidagi faylni ham "chiroyli" qildingiz. Diff ikki barobar oshdi. Yo'l-yo'lakay tuzatish — alohida PR.
10.2 Shablonni o'chirib tashlash
Shablon bo'limlarini "kerak emas" deb o'chirish — reviewer'ga signal: muallif o'ylamagan. Bo'lim haqiqatan tegishli bo'lmasa — o'chirmang, "yo'q" deb yozing: "migratsiya yo'q". Bu ham ma'lumot.
10.3 Noto'g'ri base
Stacked PR'ni main ga ochsangiz, reviewer ikki PR'ni birga ko'radi. Yoki teskarisi: oddiy PR adashib boshqa branch'ga ochilgan — merge bo'ladi, lekin main ga yetmaydi va Closes #… issue'ni yopmaydi (Pull Request darsidagi shart).
10.4 Squash'dan keyin rebase main konflikti
«Stacked PR'lar» bo'limidagi holat: o'z kodingiz bilan konflikt. Davosi — git rebase --abort, keyin git rebase --onto main <eski-pastki-branch>.
10.5 CI qizil, lekin "review qilib turing"
Test tuzalgach kod o'zgaradi va review qaytadan boshlanadi. Qizil bo'lsa — draft, yashil bo'lgach — "Ready for review".
11. Mashqlar
Mashqlar kurs/mashqlar/32/10-pr/ da. 2-mashq yechimi Node 24.21.0 da, 3-mashq yechimi Git 2.54.0 da tekshirilgan (biz ishga tushirdik).
1-mashq (oson): bo'shliqlarni to'ldiring
- GitHub PR shablonini oladigan fayl —
.github/ - Branch
maindan ajralgandan beri o'zgargan fayllar ro'yxati —git diff --stat mainHEAD - Qator oxiridagi ortiqcha bo'shliqni topadigan bayroq —
git diff -- - Hali tayyor bo'lmagan PR'ni ochish —
gh pr create -- - Squash'dan keyin yuqori branch'ni ko'chirish —
git rebase --main docs/hissa-qoshish docs/readme
Yechim
- pull_request_template.md — ildizda yoki
docs/da ham bo'lishi mumkin. - ... — uchta nuqta: ajralish nuqtasidan beri faqat sizning o'zgarishlaringiz.
- check — xato bo'lsa chiqish kodi 2.
- draft — tayyor bo'lgach
gh pr ready. - onto — faqat eski pastki branch'dan keyingi commitlar ko'chadi.
2-mashq (o'rta): tavsif tekshiruvchisi
tavsifniTekshir(tavsif) funksiyasini yozing. U PR tavsifini (Markdown matn) oladi va kanon shablonining to'rtta majburiy bo'limini tekshiradi: "Nima o'zgardi", "Nega", "Qanday tekshirildi", "Xavf va qaytarish". Qaytaradi: yoq — umuman yo'q bo'limlar, bosh — sarlavha bor, lekin ichida faqat HTML izoh yoki bo'sh joy. Ishora: ## bilan boshlangan qator — yangi bo'lim (startsWith, Matn ichida qidirish); bo'limlar matnini Map da yig'ing (Map); izohlarni olib tashlash — replace(/<!--[\s\S]*?-->/g, "") (RegExp asoslari).
Yechim
const MAJBURIY = [
"Nima o'zgardi", "Nega", "Qanday tekshirildi", "Xavf va qaytarish",
];
function tavsifniTekshir(tavsif) {
const bolimlar = new Map();
let joriy = null;
for (const qator of tavsif.split("\n")) {
if (qator.startsWith("## ")) {
joriy = qator.slice(3).trim();
bolimlar.set(joriy, "");
} else if (joriy) {
bolimlar.set(joriy, bolimlar.get(joriy) + qator + "\n");
}
}
const yoq = [];
const bosh = [];
for (const nom of MAJBURIY) {
if (!bolimlar.has(nom)) {
yoq.push(nom);
continue;
}
const matn = bolimlar.get(nom).replace(/<!--[\s\S]*?-->/g, "");
if (matn.trim() === "") bosh.push(nom);
}
return { yoq, bosh };
}
const pr15 = [
"## Nima o'zgardi", "README qayta tuzildi.",
"## Nega", "README 86 qator edi.",
"## Qanday tekshirildi", "- [x] `npm run check` yashil",
"## Review uchun", "Faqat ko'chirilgan bloklar.",
].join("\n");
const toldirilmagan = [
"## Nima o'zgardi", "<!-- 1–3 gap: nima qilindi.",
"Sarlavha — conventional commit shaklida -->",
"## Nega", "Closes #12",
"## Qanday tekshirildi", "<!-- qaysi so'rov, qaysi natija -->",
"## Xavf va qaytarish", "- [x] migratsiya yo'q",
].join("\n");
console.log(tavsifniTekshir(pr15));
console.log(tavsifniTekshir(toldirilmagan));Konsolda:
{ yoq: [ 'Xavf va qaytarish' ], bosh: [] }
{ yoq: [], bosh: [ "Nima o'zgardi", 'Qanday tekshirildi' ] }Birinchi kirish — kanon PR #15 tavsifining qisqartmasi: «Biz shunday xato qildik» bo'limidagi topilma avtomatik chiqdi. Ikkinchisi — shablon ochilgan, lekin to'ldirilmagan: izohlar turibdi, matn yo'q. [\s\S]*? — har qanday belgi, qatorlar orasida ham, "dangasa" (eng qisqa moslik), shuning uchun ikki qatorli izoh ham olib tashlandi. Bunday funksiyani CI qadami qilsa bo'ladi — GitHub Actions chuqur darsida ko'ramiz.
3-mashq (qiyin): stack'ni qutqarish
kurs/mashqlar/32/10-pr/stack-yarat.sh «Stacked PR'lar» bo'limidagi holatni yaratadi: pastki PR (docs/hissa-qoshish, ikki commit) squash bilan main ga tushgan, docs/readme esa eski commitlar ustida. Vazifa:
docs/readmePR'iga hozir qaysi commitlar kiradi — ko'rsating.git rebase mainni sinang, natija kodini chiqaring va bekor qiling.--ontobilan to'g'ri ko'chiring va PR'da endi faqat bitta commit va bitta fayl qolganini ko'rsating.- Pastki branch'ni o'chiring va qolgan branch'larni chiqaring.
Ishora: SHA'lar darsdagidek chiqishi uchun rebase'dan oldin committer'ni qotiring (GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL, GIT_COMMITTER_DATE). Squash qilingan branch git branch -d bilan o'chmaydi ("not fully merged") — -D kerak (Pull Request darsidagi tozalash).
Yechim
bash stack-yarat.sh stack > /dev/null && cd stack
export GIT_COMMITTER_NAME="Aziz Karimov"
export GIT_COMMITTER_EMAIL="aziz@example.com"
export GIT_COMMITTER_DATE="2026-11-04T10:30:00+05:00"
git log --oneline main..docs/readme
git rebase -q main > /dev/null 2>&1; echo "rebase main: exit $?"
git rebase --abort
git rebase -q --onto main docs/hissa-qoshish docs/readme
git log --oneline main..docs/readme
git diff --stat main...docs/readme
git branch -q -D docs/hissa-qoshish
git branch --format='%(refname:short)'Biz ishga tushirdik:
044cec5 docs: README qayta tuzildi (2/2)
3c068f3 docs: branch nomlash qoidasi
e9527f5 docs: CONTRIBUTING va PR shabloni (1/2)
rebase main: exit 1
e5bf4d5 docs: README qayta tuzildi (2/2)
README.md | 2 ++
1 file changed, 2 insertions(+)
docs/readme
mainOldin PR'da uchta commit bor edi — ikkitasi allaqachon main da squash shaklida. Oddiy rebase konflikt bilan to'xtadi (exit 1). --onto dan keyin — bitta commit, bitta fayl: reviewer faqat README'ni ko'radi. main..docs/readme (ikki nuqta) — main da yo'q commitlar; main...docs/readme (uch nuqta) diff'da — ajralish nuqtasidan beri o'zgarishlar.
12. Real ishda
- Qayerda uchraydi: deyarli har jamoada PR shabloni va "kichik PR" kelishuvi bor. Ba'zi kompaniyalar PR hajmi va review kutish vaqtini jamoa metrikasi sifatida kuzatadi.
- Ochiq loyihalarda: begona loyihaga birinchi PR'ingiz (Open source darsida) — aynan shu darsdagi odatlar bilan qabul qilinadi yoki yopiladi.
- Intervyu savollari: "Yaxshi PR qanday bo'ladi?", "Katta o'zgarishni qanday bo'lasiz?", "PR tavsifiga nima yozasiz?", "Stacked PR nima va squash bilan qanday ishlaydi?"
Xulosa
- Kichik PR (≈ 200–400 qator) tezroq va sinchiklab ko'riladi; mustaqil o'zgarishlar — alohida PR. Kanon PR #9 (7 tuzatish, 511 qator) — teskari misol.
- Sarlavha — Conventional Commits shaklida: squash'dan keyin u
maindagi commit xabari. - PR shabloni: nima, nega, qanday tekshirildi, review uchun, xavf va qaytarish.
gh pr create --body-fileshablonni chetlab o'tadi — kanonda shunday bo'ldi. - Self-review:
git log main..HEAD,git diff --stat main...HEAD,git diff --check, to'liq diff'ni o'qish. - Draft — erta savol uchun; stacked PR'da base — pastki branch, squash'dan keyin
git rebase --onto.
Keyingi dars: Code review berish va olish — reviewer nimaga qaraydi, Conventional Comments (muammo:, taklif:, savol:), o'z PR'ingizni tasdiqlay olmaslik va muhokamalar yopilmaguncha merge yo'q.
Manbalar
- Google Engineering Practices — Small CLs: https://google.github.io/eng-practices/review/developer/small-cls.html (sinalmagan, 2026-11)
- Google Engineering Practices — Writing good CL descriptions: https://google.github.io/eng-practices/review/developer/cl-descriptions.html (sinalmagan, 2026-11)
- GitHub Docs — Creating a pull request template for your repository: https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository (sinalmagan, 2026-11)
- GitHub Docs — Pull requests (draft): https://docs.github.com/en/pull-requests/reference/pull-requests
- GitHub Docs — Merging a pull request (base'ni avtomatik almashtirish): https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/merging-a-pull-request
- GitHub CLI —
gh pr create --help(gh 2.92.0,--template,--draft) - Git hujjati — git-rebase (
--onto,--update-refs): https://git-scm.com/docs/git-rebase - Git hujjati — git-diff (
--check,--shortstat): https://git-scm.com/docs/git-diff - Kurs sinov reposi — PR #9, #13–#15, #17–#19 hajmi va tavsiflari (
gh pr list,gh pr viewbilan o'qildi, 2026-11-04): https://github.com/Sarvarbek0704/ilmhamroh-git-sinov/pulls?q=is%3Apr - Kanon tajribasi (IlmHamroh, 2026-11-04): PR shabloni va
CONTRIBUTING.md(loyihaning shu bosqichi). Self-review buyruqlari, stacked PR, squash'dan keyingi konflikt varebase --onto, mashq yechimlari — biz ishga tushirdik (2026-11-04).
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!