IlmHamroh
JavaScript Full-stack/32-qism. Professional Git va jamoada ishlash6/19-dars19 daqiqa
Mundarija (37)

Katta repolar: shallow clone, partial clone, sparse-checkout va Git LFS

Qisqacha: Git har klonga butun tarixni — har faylning har versiyasini — olib keladi. Repo katta bo'lsa (ko'p fayl, ko'p yillik tarix yoki binar fayllar), bu sekin va og'ir. To'rtta yechim bor. Shallow clone (--depth 1) — tarixsiz faqat oxirgi holat. Partial clone (--filter=blob:none) — butun tarix, lekin fayl mazmuni faqat kerak bo'lganda; sparse-checkout — ishchi papkada faqat kerakli papkalar; Git LFS — katta binar fayllar repodan tashqarida, repo'da kichik ko'rsatkich. O'quv tajribasida 15.6 MB lik repo'ning to'liq klonidagi 16 MB .git partial clone bilan 740 KB ga, sparse bilan 211 KB ga tushdi. Har birining narxi bor: git log -p yoki blame kerak bo'lganda yo'q narsa tarmoqdan yuklanadi.

Bu darsda

  • Klon nimani olib kelishini va qayerda og'irlashishini o'lchaysiz.
  • --depth, --deepen, --unshallow bilan sayoz klonda ishlaysiz.
  • --filter=blob:none va blob:limit bilan partial clone qilasiz va "yo'q obyekt"larni sanaysiz.
  • sparse-checkout bilan faqat kerakli papkalarni ochasiz.
  • Git LFS bilan binar fayllarni ko'chirasiz, jumladan mavjud tarixni git lfs migrate bilan.

Oldin bilishingiz kerak: Git ichkaridan: obyektlar, SHA va snapshot, .gitattributes va qator oxirlari, Remote: clone, fetch, pull, push, Kod arxeologiyasi: blame, log -S, log -L.

1. Nega bu kerak?

Git ichkaridan darsini eslang: Git har commitda butun loyihaning suratini (snapshot) saqlaydi. O'zgarmagan fayl takrorlanmaydi, lekin o'zgargan har versiya — alohida blob obyekt. Matnli fayllar uchun bu arzon: Git ularni siqadi va bir-biridan farq (delta) sifatida saqlaydi. Binar fayllar — videolar, rasmlar, dizayn fayllari — esa yomon siqiladi. 10 MB lik videoning har versiyasi deyarli 10 MB qo'shadi.

git clone sukut bo'yicha hammasini olib keladi: har commit, har daraxt, har blob. Bu Git'ning kuchi — internet yo'q joyda ham butun tarix qo'lingizda. Lekin uch holatda bu og'ir:

  • CI. Har yugurishda yangi klon. Testlarga faqat oxirgi holat kerak, tarix emas.
  • Monorepo. Repo'da 10 ta loyiha, sizga bittasi kerak (keyingi dars).
  • Binar fayllar. Dizayner har kuni .psd ni yangilaydi — bir yilda repo gigabaytlarga yetadi.

GitHub hujjatiga ko'ra (2026-11 holatiga), 50 MiB dan katta faylda Git ogohlantiradi, 100 MiB dan katta faylni GitHub rad etadi. Repo'ni 1 GB dan kichik tutish tavsiya qilinadi, 5 GB dan kichik — qat'iy tavsiya. Bu chegaralarni biz o'zimiz sinamadik.

Hayotiy o'xshatish: kutubxonaga a'zo bo'ldingiz. To'liq klon — har kitobning har nashrini uyga tashish. Shallow — faqat oxirgi nashrlar. Partial — katalog va kitob kartochkalari uyda, kitobning o'zi so'raganingizda keltiriladi. Sparse — faqat "Tarix" bo'limi javonlari. LFS — og'ir albomlar omborda, javonda esa "albom №17, 3 kg, omborda" degan kartochka.

2. O'quv repo va o'lchov usuli

2.1 Repo

«Bahor» choyxonasining sayt repo'si: sayt/ da 200 HTML, api/ da 200 JS, docs/ da 100 Markdown fayl va media/menyu-video.bin — 512 KB lik "video". Video 30 marta yangilangan, har safar api/f1.js ga bitta qator qo'shilgan. Repo'ni kurs/mashqlar/32/06-katta-repo/katta-repo-yarat.sh yaratadi: bash katta-repo-yarat.sh sayt. Binar mazmun tasodifiy ko'rinadi (siqilmaydi), lekin qotirilgan — SHA'lar sizda ham darsdagidek. Skript ~30 soniya ishlaydi.

bash
git -C sayt rev-list --count HEAD
git -C sayt ls-files | wc -l
git -C sayt count-objects -vH | grep size-pack

Terminalda:

text
31
501
size-pack: 15.56 MiB

31 commit, 501 fayl, siqilgan holda 15.56 MiB. Bunning deyarli hammasi — videoning 31 versiyasi (31 × 512 KB ≈ 15.5 MB). 500 ta matn fayli bir necha kilobayt.

2.2 Qanday o'lchaymiz

Ikki ko'rsatkich. Birinchisi — .git papka hajmi (du -sk, kilobayt). Ikkinchisi — yo'q obyektlar soni:

bash
git rev-list --objects --all --missing=print | grep -c '^?'

rev-list --objects --all — tarixdagi hamma obyekt ro'yxati. --missing=print — repo'da yo'q obyektlarni ? belgisi bilan chiqaradi (xato bermasdan). To'liq klonda bu son 0. Bu ko'rsatkich vaqtdan yaxshiroq: vaqt mashinaga bog'liq, son esa sizda ham xuddi shunday chiqadi.

Klonlar file:// manzili orqali olinadi — bu haqiqiy Git transporti, faqat tarmoqsiz. Lokal papkadan klon qilganda Git odatda .git fayllarini shunchaki nusxalab qo'ya qoladi. --no-local bu qisqa yo'lni o'chiradi va haqiqiy klon qiladi — xuddi serverdan olgandek:

bash
URL="file://$(pwd)/sayt"
git clone -q --no-local "$URL" k-toliq

Windows Git Bash'da $(pwd) /c/Users/... ko'rinishida; dars o'lchovlarida biz uni cygpath -m bilan C:/Users/... ga o'girdik, mashq skripti esa $(pwd) ning o'zi bilan ishladi.

3. Shallow clone — sayoz klon

3.1 --depth 1

bash
git clone -q --no-local --depth 1 "$URL" k-sayoz
cd k-sayoz
git rev-parse --is-shallow-repository
git log --oneline

Terminalda:

text
true
41ce89d (grafted, HEAD -> main, origin/main, origin/HEAD) chore: menyu videosi 30

Sayoz klon (shallow clone) — faqat oxirgi N ta commit. --depth 1 — bitta. grafted ("payvandlangan") — Git bu commitning otasi borligini biladi, lekin u yerda yo'q. Chegara .git/shallow fayliga yoziladi.

Natija: .git — 672 KB (to'liqda 16 051 KB). 24 baravar kichik.

3.2 Narxi: tarix yo'q

bash
git log --oneline -- api/f1.js | wc -l
git blame -L1,2 api/f1.js
text
1
^41ce89d (Aziz Karimov 2026-10-17 10:00:00 +0500 1) export const f1 = 1;
^41ce89d (Aziz Karimov 2026-10-17 10:00:00 +0500 2) // o'zgarish 1

api/f1.js 31 marta o'zgargan, lekin log bitta commit ko'rsatadi. blame esa yolg'on gapiradi: ikkala qatorni ham oxirgi commitga yozdi. ^ belgisi — "chegara commiti": bundan oldingisi ko'rinmaydi. Haqiqatda birinchi qator birinchi commitdan, ikkinchisi — "o'zgarish 1" commitidan. Kod arxeologiyasi darsidagi vositalar sayoz klonda ishlamaydi.

3.3 Chuqurlashtirish

Tarix kerak bo'lib qolsa, qayta klon shart emas:

bash
git fetch -q --deepen=5
git rev-list --count HEAD
git fetch -q --unshallow
git rev-list --count HEAD
git rev-parse --is-shallow-repository
text
6
31
false

--deepen=5 — yana 5 commit. --unshallow — butun tarix, repo oddiy klonga aylandi.

Qachon mos: CI'da build va test — u yerda tarix kerak emas. GitHub Actions'dagi actions/checkout ham sukut bo'yicha fetch-depth: 1 bilan sayoz klon qiladi (actions/checkout README, 2026-11; Actions'da sinalmagan) — GitHub Actions darsidagi workflow ham shunday klonlanadi. Lekin CI'da CHANGELOG va reliz kabi tarixga qaraydigan qadam bo'lsa — fetch-depth: 0 (to'liq) kerak. Aks holda vosita "commitlar yo'q" deb noto'g'ri versiya chiqaradi.

4. Partial clone — qisman klon

4.1 --filter=blob:none

Sayoz klonning muammosi — tarix yo'q. Qisman klon (partial clone) boshqacha kelishuv taklif qiladi: commitlar va daraxtlar (kim, qachon, qaysi fayl) — hammasi, fayl mazmuni (blob) — faqat kerak bo'lganda.

bash
git clone -q --no-local --filter=blob:none "$URL" k-blobsiz

To'rt klon turini solishtiramiz:

Klon .git, KB Yo'q obyekt
to'liq 16 051 0
--depth 1 672 0
--filter=blob:none 740 60
--filter=blob:limit=100k 697 30

Blobsiz klon deyarli sayozdek kichik, lekin unda 31 commitning hammasi bor. 60 yo'q obyekt — videoning 30 eski versiyasi va api/f1.js ning 30 eski versiyasi. Joriy holat (HEAD) fayllari klon paytida yuklandi — ishchi papka to'liq.

blob:limit=100k — "100 KB dan katta blob'larni yuklama". Kichik f1.js versiyalari keldi, faqat 30 ta eski video yo'q. Variantlar ichida bu eng nozigi: matn tarixi to'liq, og'ir binarlar — talab bo'yicha.

4.2 Talab bo'yicha yuklash

Klon o'zining manbasini eslab qoladi:

bash
git config --get remote.origin.promisor
git config --get remote.origin.partialclonefilter
git show HEAD~10:media/menyu-video.bin | wc -c
text
true
blob:none
524288

promisor — "va'da beruvchi" remote: "yo'q obyekt kerak bo'lsa, menda bor". git show videoning 10 commit oldingi versiyasini so'radi — Git uni jimgina yuklab keldi (524 288 bayt). Yo'q obyektlar soni 60 dan 59 ga tushdi.

4.3 Narxi: tarix arxeologiyasi

Qaysi buyruqlar blob talab qiladi?

bash
git log --oneline -- api/f1.js | wc -l
git log -p -- media/ > /dev/null

Biz ishga tushirdik (o'lchov skriptimiz har buyruqdan keyin yo'q obyektlar sonini ham chiqardi):

text
31
log -- media/ (faqat commitlar): yo'q 59
log -p -- media/: yo'q 30, .git 16430 KB

git log -- api/f1.js — 31 ta commit, hech narsa yuklanmadi. "Qaysi commit faylni o'zgartirdi" savoliga daraxtlar javob beradi, ular esa klonda bor. git log -p esa har versiyaning mazmunini ko'rsatadi — 29 ta video bir-bir yuklandi va .git to'liq klon hajmiga yetdi.

Kanon tajribasida (IlmHamroh, 2026-11) 60 MB lik video tarixida xuddi shu git log -p media/ 17.2 soniya davom etdi, to'liq klondagi esa bir zumda. Sabab: har blob uchun alohida so'rov. Haqiqiy tarmoqda — GitHub'gacha — bu yanada sekin. Ya'ni partial clone — qarz: hozir tez, lekin blame, log -p, eski commitga checkout qilganingizda tarmoq orqali qaytariladi. Tarmoq yo'q bo'lsa — buyruq yiqiladi.

Tekshirib ko'ring: CI'da faqat npm test ishga tushadi. Sayoz klon (--depth 1) yoki blobsiz klon (--filter=blob:none) — qaysi biri mos va nega?

Javob

Ikkalasi ham ishlaydi, sayoz — biroz kichikroq (672 va 740 KB). Testlarga tarix kerak emas. Lekin CI'da tarixga qaraydigan qadam bo'lsa (reliz vositasi, "oxirgi tagdan beri nima o'zgardi"), blobsiz klon yaxshiroq: commitlar to'liq, faqat eski fayl mazmuni yo'q. Sayoz klonda bunday vosita jim noto'g'ri natija beradi.

5. Sparse-checkout — faqat kerakli papkalar

5.1 Cone rejimi

Partial clone .git ni kichraytiradi, lekin ishchi papka to'liq — 501 fayl. Sizga faqat api/ kerak bo'lsa-chi? sparse-checkout (siyrak checkout) — ishchi papkaga faqat tanlangan papkalarni chiqarish:

bash
git clone -q --no-local --filter=blob:none --sparse "$URL" k-sparse
cd k-sparse
git sparse-checkout set api
ls
git status | grep sparse

Terminalda:

text
api
You are in a sparse checkout with 40% of tracked files present.

--sparse bilan klon dastlab faqat ildizdagi fayllarni ochadi (bizda ular yo'q — papka bo'sh). set api — "faqat api/ ni ko'rsat". 200 fayl, kuzatilayotganlarning 40 %. Qolgan 301 fayl indeksda bor, lekin diskda yo'q: Git ularni "o'zgartirilmagan" deb hisoblaydi va status da ko'rsatmaydi.

Bu cone ("konus") rejimi — sukut. Unda faqat papkalar tanlanadi va Git tekshiruvni tez qiladi. Eski "naqsh" rejimi (.gitignore uslubidagi shablonlar) hujjatda eskirgan deb belgilangan.

Yana bir papka qo'shamiz:

bash
git sparse-checkout add docs
ls
text
api
docs

--filter=blob:none bilan birga sparse eng kuchli: faqat tanlangan papkalarning blob'lari yuklanadi. Natija — .git 211 KB, yo'q obyekt 261 (200 HTML, videoning 31 versiyasi va f1.js ning 30 eski versiyasi). Kanon tajribasida 3 000 faylli repo'da xuddi shu juftlik 562 KB va 1 000 fayl berdi — to'liq klonning 1 % i.

Hammasini qaytarish: git sparse-checkout disable.

5.2 Narxi

  • git grep va muharrir qidiruvi faqat ochilgan papkalarni ko'radi. Boshqa papkadagi chaqiruvni topa olmaysiz.
  • Build boshqa papkaga bog'liq bo'lsa (masalan api/ umumiy lib/ ni import qiladi), uni ham qo'shishni unutmang.
  • Ba'zi vositalar (eski IDE plaginlari) yarim ishchi papkani tushunmaydi.

6. Git LFS — katta fayllar repodan tashqarida

6.1 G'oya

Yuqoridagi uch usul — klon qiluvchining tanlovi. Repo esa o'zgarmaydi: videoning 31 versiyasi baribir tarixda, to'liq klon baribir 16 MB. Git LFS (Large File Storage — katta fayllar ombori) muammoni manbada hal qiladi: katta fayl alohida serverga ketadi, Git tarixida esa uning o'rnida ~130 baytlik ko'rsatkich (pointer) turadi.

flowchart LR
  subgraph Git["Git tarixi (har klonda)"]
    P1["media/menyu-video.bin<br/>ko'rsatkich: oid + size<br/>~130 bayt"]
  end
  subgraph LFS["LFS ombori"]
    V30["video, 30-versiya<br/>512 KB"]
    V29["video, 29-versiya<br/>512 KB"]
    V0["... 0-versiya"]
  end
  P1 -- "checkout paytida<br/>faqat joriy versiya" --> V30

Klonda faqat joriy commit uchun kerakli versiya yuklanadi. Eski versiyalar omborda qoladi va kerak bo'lganda yuklanadi — partial clone'ga o'xshaydi, lekin faqat siz tanlagan fayl turlari uchun.

6.2 Yangi repo'da: track

LFS — Git'ga kengaytma. Git for Windows bilan birga o'rnatiladi; macOS/Linux'da alohida (brew install git-lfs, apt install git-lfs). Kompyuterda bir marta:

bash
git lfs install

Keyin repo'da qaysi fayllar LFS'ga ketishini aytasiz:

bash
git lfs track "*.bin"
cat .gitattributes
text
*.bin filter=lfs diff=lfs merge=lfs -text

.gitattributes darsidan tanish fayl. filter=lfs — fayl git add paytida ko'rsatkichga aylantiriladi ("clean" filtri), checkout paytida asl faylga qaytariladi ("smudge" filtri). -text — qator oxirlariga tegma. .gitattributes ni commit qilish shart — aks holda hamkasbingizda *.bin oddiy fayl bo'lib qoladi.

6.3 Mavjud tarixni ko'chirish: migrate

Bizning repo'da video allaqachon 31 versiyada tarixda. track faqat keyingi commitlarga ta'sir qiladi. Butun tarixni ko'chirish uchun git lfs migrate bor. Avval — nima og'ir:

bash
git lfs migrate info --everything

Biz ishga tushirdik (yangi klonda):

text
*.bin 	16 MB 	  31/31 files	100%
*.js  	13 KB 	230/230 files	100%
*.html	3.5 KB	200/200 files	100%
*.md  	1.2 KB	100/100 files	100%

Tasvir aniq: 16 MB — .bin, qolgani kilobaytlar. Ko'chiramiz:

bash
git lfs migrate import --everything --include="*.bin"
git cat-file -p HEAD:media/menyu-video.bin
git lfs ls-files
text
version https://git-lfs.github.com/spec/v1
oid sha256:4a8e2abaf82c69f2f7597081aa269c4b103690f882255cce7261e3de44bf4690
size 524288
4a8e2abaf8 - media/menyu-video.bin

Git'da endi faylning o'rnida uch qator: spetsifikatsiya versiyasi, mazmunning SHA-256 xeshi (oid — LFS'dagi nomi) va asl hajmi. ls-files — LFS'dagi joriy fayllar.

Diqqat: migrate import --everything — bu Tarixni qayta yozish darsidagi jarayonning o'zi. Har commit yangi hash oladi, majburiy push kerak, hamkasblar qayta klon qiladi. O'tgan darsdagi hamma ogohlantirish shu yerda ham amal qiladi. Eski obyektlarni tozalagach (git reflog expire --expire=now --all && git gc --prune=now):

text
.git/objects 93 KB, .git/lfs 15876 KB

Git tarixi 16 MB dan 93 KB ga tushdi. 15.9 MB — lokal LFS keshida (.git/lfs), u Git obyektlari emas.

6.4 LFS klon

bash
git clone -q "$LURL" l-klon
GIT_LFS_SKIP_SMUDGE=1 git clone -q "$LURL" l-skip

$LURL — LFS'ga ko'chirilgan repo manzili. Biz ishga tushirdik (hajmlarni du va stat bilan o'lchab):

text
LFS klon: .git 699 KB, lfs 512 KB, fayl 524288 bayt
SKIP_SMUDGE: .git 187 KB, fayl 131 bayt

Oddiy LFS klon videoning faqat joriy versiyasini yukladi — 512 KB, 31 tasi emas. Kanon tajribasida 60 versiyali 1 MB video bilan ham shunday: klonga faqat 1 024 KB keldi, manbaning LFS keshi esa 61 MB edi.

GIT_LFS_SKIP_SMUDGE=1 — "asl fayllarni umuman yuklama". Diskda 131 baytlik ko'rsatkich qoladi. CI'da LFS fayllari kerak bo'lmasa (masalan, faqat backend testlari) — eng tez yo'l. Kerak bo'lganda tanlab yuklanadi:

bash
git lfs pull --include="media/*"
stat -c "%s bayt" media/menyu-video.bin
text
524288 bayt

6.5 Narxi

  • Server kerak. LFS fayllari Git serverining LFS omboriga ketadi. GitHub hujjatiga ko'ra (2026-11 holatiga), bitta fayl chegarasi Free va Pro'da 2 GB, Team'da 4 GB, Enterprise Cloud'da 5 GB; saqlash va trafik — alohida hisob-kitob. Biz LFS'ni GitHub'ga yubormadik — kvota va narx sinalmagan.
  • Har kompyuterda git lfs install. Bo'lmasa klonda video o'rnida ko'rsatkich matni turadi va dastur "buzuq fayl" deydi.
  • Arxivlar. GitHub'ning "Download ZIP" arxiviga LFS fayllari kiradimi — repo sozlamasiga bog'liq (GitHub hujjati).
  • Ko'chirish — tarixni qayta yozish. LFS'ni loyiha boshida yoqish arzon, keyin — qimmat.

7. Qaysi birini tanlash

Avval bir rasmda — «Bahor» repo'sining to'rt xil klonidagi .git hajmi. Ustunlarning uzunligiga qarang: to'liq klon qolganlaridan 20 baravardan ko'proq.

«Bahor» sayt repo'si: klon turiga qarab .git hajmi
  • to'liq16 051 KB
  • --depth 1672 KB
  • blob:none740 KB
  • blob:limit=100k697 KB
  • blob:none + sparse211 KB

Manba: IlmHamroh o'quv tajribasi, 2026-11-04: Git 2.54.0, Windows 11, du -sk; bitta mashina

Lekin hajm — hikoyaning yarmi. Har ustunning narxi bor — mana ular bitta jadvalda:

Muammo Yechim Kim tanlaydi Narxi
CI'da tez klon --depth 1 klon qiluvchi tarix yo'q, blame yolg'on
Tarix kerak, mazmun kam --filter=blob:none klon qiluvchi log -p va blame tarmoqqa boradi
Ulkan repo, kerak bitta papka sparse + blobsiz klon qiluvchi qidiruv faqat ochilgan papkalarda
Binar fayllar tarixi Git LFS repo egasi server, kvota, ko'chirish qiyin

Birinchi uchtasini istalgan dasturchi istalgan repo'da o'zi tanlaydi — repo o'zgarmaydi. LFS — jamoaviy qaror, .gitattributes orqali hammaga ta'sir qiladi.

Yana bir vosita: git maintenance. U fonda commit-graph, siqish va keraksiz obyektlarni tozalashni bajaradi — katta repo'da git log, git status tezlashadi. Uni Git konfiguratsiyasi va unumdorlik darsida o'lchaymiz.

8. Loyiha qadami: vazifalar-api uchun xulosa

Bu dars — tajriba darsi: vazifalar-api kodi o'zgarmaydi va commit yo'q. Loyiha katta emas — 145 ta .ts fayl va 75 ta test fayli, binar fayl yo'q (kanon tekshiruvi: 1 MB dan katta fayl 0). LFS kerak emas. Lekin ikki xulosa bor:

  1. CI fayli. .github/workflows/ci.yml dagi actions/checkout sayoz klon qiladi. Hozir bu to'g'ri: testlarga tarix kerak emas. Reliz vositasini CI'ga qo'shsangiz (CHANGELOG va reliz), u qadamga fetch-depth: 0 qo'shing.
  2. Binar qoidasi. Loyihaga rasm, PDF yoki model fayli qo'shish kerak bo'lsa — avval git lfs track va .gitattributes, keyin birinchi commit.

O'z repo'ngizda tekshiring — eng katta 5 obyekt:

bash
git rev-list --objects --all \
  | git cat-file --batch-check='%(objectsize) %(rest)' \
  | sort -rn | head -5

Bir necha yuz kilobaytdan katta narsa bo'lsa — o'ylang: u repo'da bo'lishi kerakmi?

9. Ko'p uchraydigan xatolar

9.1 Sayoz klonda reliz vositasi noto'g'ri versiya berdi

Tarix bitta commit — vosita "oxirgi tag" ni topa olmadi. Davosi: git fetch --unshallow yoki CI'da fetch-depth: 0.

9.2 Partial clone'da buyruq "osilib qoldi"

blame yoki log -p yuzlab blob'ni bir-bir yuklayapti. Bu xato emas — narx. Tez-tez kerak bo'lsa, oddiy klonga o'ting yoki blob:limit bilan faqat og'ir fayllarni chiqarib tashlang.

9.3 Klondan keyin video "buzuq"

Fayl ochilmaydi, hajmi ~130 bayt, ichida version https://git-lfs... matni. Bu — ko'rsatkich: git lfs install qilinmagan. Davosi: git lfs install, keyin git lfs pull.

9.4 track qildim, lekin tarix baribir og'ir

track faqat keyingi commitlarga ta'sir qiladi. Eski versiyalar uchun — git lfs migrate import va uning hamma oqibatlari.

9.5 Sparse'da kod topilmadi

Qidiruv faqat ochilgan papkalarda. git grep ni boshqa papka uchun ishlatish kerak bo'lsa — git sparse-checkout add <papka> yoki vaqtincha disable.

10. Mashqlar

Mashqlar kurs/mashqlar/32/06-katta-repo/ 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

  • Faqat oxirgi commit bilan klon: git clone --depth
  • Sayoz klonni to'liqqa aylantirish: git fetch
  • Fayl mazmunisiz, lekin butun tarix bilan klon: --filter=
  • Faqat api/ papkasini ochish: git sparse-checkout api
  • LFS fayllarini yuklamasdan klon qiladigan muhit o'zgaruvchisi —
Yechim
  • 1 — grafted belgili bitta commit.
  • --unshallow — yoki --deepen=N qisman.
  • blob:none — yoki blob:limit=100k.
  • set — add yana papka qo'shadi.
  • GIT_LFS_SKIP_SMUDGE — =1, keyin git lfs pull --include=....

2-mashq (o'rta): LFS ko'rsatkichi

lfsKorsatkich(mazmun) funksiyasini yozing: fayl mazmunidan LFS ko'rsatkichini yasasin — «Mavjud tarixni ko'chirish: migrate» bo'limidagi uch qator, har biri \n bilan tugaydi. Teskarisi — korsatkichniOqi(matn): ko'rsatkich bo'lsa { oid, hajm }, bo'lmasa null. LFS spetsifikatsiyasiga ko'ra ko'rsatkich 1024 baytdan kichik. Ishora: SHA-256 — node:crypto dagi createHash("sha256"); hajm — belgilar emas, baytlar (Buffer.byteLength); qatorlarni muntazam ifoda bilan tekshiring.

Yechim
js
import { createHash } from "node:crypto";

const VERSIYA = "version https://git-lfs.github.com/spec/v1";

function lfsKorsatkich(mazmun) {
  const oid = createHash("sha256").update(mazmun).digest("hex");
  const hajm = Buffer.byteLength(mazmun);
  return `${VERSIYA}\noid sha256:${oid}\nsize ${hajm}\n`;
}

function korsatkichniOqi(matn) {
  const q = matn.split("\n");
  if (q[0] !== VERSIYA || matn.length > 1024) return null;
  const oid = q[1]?.match(/^oid sha256:([0-9a-f]{64})$/)?.[1];
  const hajm = Number(q[2]?.match(/^size (\d+)$/)?.[1]);
  return oid && Number.isInteger(hajm) ? { oid, hajm } : null;
}

const k = lfsKorsatkich("salom dunyo\n");
console.log(k);
console.log(korsatkichniOqi(k));
console.log(korsatkichniOqi("<p>sahifa 1</p>\n"));
console.log(Buffer.byteLength(k), "bayt");

Konsolda:

text
version https://git-lfs.github.com/spec/v1
oid sha256:024916b14c709fe90760ca085b44165bad443ab6d07cee6010763e8c5e289040
size 12

{
  oid: '024916b14c709fe90760ca085b44165bad443ab6d07cee6010763e8c5e289040',
  hajm: 12
}
null
127 bayt

Bu kod node:crypto va Buffer ni ishlatadi — ular faqat Node'da bor, shuning uchun saytda "Ishga tushir" tugmasi yo'q: uni kompyuteringizda node bilan ishga tushiring. Funksiya to'g'rimi? LFS'ning o'zida tekshiramiz: printf 'salom dunyo\n' > p.txt && git lfs pointer --file=p.txt — biz ishga tushirdik, oid va size aynan shunday chiqdi. Ko'rsatkich 127 bayt; darsdagi videoning ko'rsatkichi 131 bayt — farq size qatoridagi raqam uzunligida (12 va 524288). Oddiy HTML fayl ko'rsatkich emas — null.

3-mashq (qiyin): nima yuklandi, nima yo'q

katta-repo-yarat.sh bilan sayt repo'sini yarating. Undan blobsiz va --sparse klon oling, faqat api/ ni oching. Keyin bosqichma-bosqich docs/ ni qo'shing, videoning 10 commit oldingi versiyasini o'qing va api/f1.js tarixini ko'ring. Har bosqichdan keyin ikki sonni chiqaring: ishchi papkadagi fayllar va yo'q obyektlar. Qaysi qadam obyekt yukladi, qaysi — yo'q?

Ishora: git ls-files -t sparse'da ochilgan fayllarni H, yopilganlarni S belgisi bilan ko'rsatadi. Yo'q obyektlar — «Qanday o'lchaymiz» bo'limidagi buyruq. Ikkalasini bitta bash funksiyasiga yig'ing.

Yechim
bash
bash katta-repo-yarat.sh sayt
URL="file://$(pwd)/sayt"

holat() {
  local f=$(git ls-files -t | grep -c '^H')
  local y=$(git rev-list --objects --all --missing=print \
    | grep -c '^?')
  echo "$1: ishchi papkada $f fayl, yo'q obyekt $y"
}

git clone -q --no-local --filter=blob:none --sparse "$URL" k
cd k
git sparse-checkout set api
holat "api"
git sparse-checkout add docs
holat "api+docs"
git show HEAD~10:media/menyu-video.bin | wc -c
holat "eski video"
git log --oneline -- api/f1.js | wc -l
holat "log"

Biz ishga tushirdik:

text
api: ishchi papkada 200 fayl, yo'q obyekt 361
api+docs: ishchi papkada 300 fayl, yo'q obyekt 261
524288
eski video: ishchi papkada 300 fayl, yo'q obyekt 260
31
log: ishchi papkada 300 fayl, yo'q obyekt 260

Hisob: tarixda 501 + 30 + 30 = 561 blob (joriy fayllar, videoning 30 eski versiyasi, f1.js ning 30 eski versiyasi). api bosqichida 200 tasi bor, 361 yo'q. add docs 100 blob yukladi. git show — bitta. git log -- api/f1.js — hech narsa: tarix daraxtlardan o'qildi. Hozir git log -p -- api/f1.js yozsangiz, 30 ta eski versiya yuklanadi — sinab ko'ring. Windows Git Bash'da file://$(pwd) ishladi; ishlamasa, cygpath -m bilan yo'lni o'giring.

11. Real ishda

  • Qayerda uchraydi: o'yin studiyalari (teksturalar, modellar) va ML jamoalari (model fayllari) — LFS; katta kompaniyalarning monorepo'lari — partial clone va sparse; deyarli har CI — sayoz klon.
  • Scalar. Git bilan birga keladigan scalar buyrug'i katta repo uchun hammasini birdaniga yoqadi: blobsiz klon, sparse, fon xizmati (sinalmagan, 2026-11).
  • Intervyu savollari: "Repo 5 GB, klon 20 daqiqa — nima qilasiz?", "Shallow va partial clone farqi?", "Git LFS qanday ishlaydi, ko'rsatkich fayli nima?"

Xulosa

  • To'liq klon har faylning har versiyasini olib keladi; binar fayllarda bu tez og'irlashadi.
  • --depth 1 — eng kichik, lekin tarix yo'q: log bitta commit, blame noto'g'ri; --deepen, --unshallow bilan qaytariladi.
  • --filter=blob:none — butun tarix, mazmun talab bo'yicha; log -p va blame tarmoq orqali to'lanadi.
  • sparse-checkout (cone) — ishchi papkada faqat kerakli papkalar; blobsiz klon bilan juft eng kichik.
  • Git LFS — katta fayllar omborda, Git'da ~130 baytlik ko'rsatkich; klonga faqat joriy versiya keladi.
  • Mavjud tarixni LFS'ga ko'chirish (migrate import) — tarixni qayta yozish.
  • Birinchi uchtasi — klon qiluvchining tanlovi, LFS — repo'ning qarori.

Keyingi dars: Git va monorepo: submodule, subtree, CODEOWNERS va path filtrlar — bitta repo'da bir nechta loyiha: umumiy kodni ulashning ikki usuli, kim nimaga javobgar va CI faqat o'zgargan qismda.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Katta repolar: shallow clone, partial clone, sparse-checkout va Git LFS — IlmHamroh