IlmHamroh
JavaScript Full-stack/32-qism. Professional Git va jamoada ishlash8/19-dars22 daqiqa
Mundarija (40)

Git konfiguratsiyasi: alias, includeIf, rerere va unumdorlik sozlamalari

Qisqacha: Git'ning yuzlab sozlamasi bor, lekin kundalik ishni bir nechtasi o'zgartiradi. Alias uzun buyruqni qisqa nomga aylantiradi. Shartli qo'shish (includeIf) esa ish papkasidagi repolarga ish emailini, qolganlariga shaxsiy emailni avtomatik qo'yadi. Sozlama push.autoSetupRemote yangi branch'ni birinchi git push dayoq yuboradi, fetch.prune serverda o'chirilgan branch'larni tozalaydi. Yana biri — rerere: bir marta yechilgan konfliktni eslab qoladi, zdiff3 esa asl versiyani ham ko'rsatadi. Katta repoda core.untrackedCache, core.fsmonitor va git maintenance tezlikka yordam beradi. Kanon tajribasida 40 ming faylli repoda git status 95 ms dan 83 ms gacha tushdi.

Bu darsda

  • Sozlamani qaysi daraja berganini --show-scope va --show-origin bilan aniqlaysiz.
  • Oddiy va ! li alias yozasiz.
  • includeIf bilan ish va shaxsiy repolarga turli email qo'yasiz va uning tuzoqlarini bilasiz.
  • push.autoSetupRemote, fetch.prune, help.autocorrect, zdiff3, rerere va histogram ni sinab, natijasini ko'rasiz.
  • Katta repoda git status va xizmat ishlarini (git maintenance) qanday tezlashtirishni tushuntirasiz.

Oldin bilishingiz kerak: Git'ni o'rnatish va birinchi sozlash, Tarixni o'qish: git log, Conflictlarni yechish amaliyoti, Remote: clone, fetch, pull, push, Katta repolar.

1. Nega bu kerak?

Git'ni o'rnatish darsida uchta sozlama yozgansiz: ism, email va main. O'shandan beri Git sizdan bir necha marta "boshqacha qilaymi?" deb so'radi. Yangi branch'ni push qilganingizda --set-upstream ni talab qildi. Konfliktda faqat ikki tomonni ko'rsatdi, asl matnni emas. Ishxona repo'siga shaxsiy emailingiz bilan commit tushdi.

Bularning hammasi — sukut qiymatlar. Git ularni ehtiyotkorlik bilan tanlagan: eski xulqni buzmaslik uchun. Siz esa o'z ishingizga mos qiymatni bir marta yozib qo'yasiz va har kuni foydasini ko'rasiz.

Hayotiy o'xshatish: yangi telefon. Zavod sozlamasida u ishlaydi, lekin klaviatura tili, yorqinlik, bildirishnomalar — har kim o'ziga moslaydi. Bir soatlik sozlash keyingi ikki yilni qulay qiladi. Git ham shunday — faqat sozlash bir soat emas, o'n daqiqa.

Bu dars — tajriba darsi. vazifalar-api kodi o'zgarmaydi, commit yo'q. Hamma buyruqni biz vaqtinchalik papkada ishga tushirdik: kompyuterning umumiy sozlamasiga tegmaslik uchun GIT_CONFIG_GLOBAL boshqa faylga qaratildi (Git'ni o'rnatish darsidagi usul). Hash va yo'llar sizda boshqacha chiqadi.

2. Sozlama qayerdan keladi

2.1 Uch daraja va yangi sintaksis

Takrorlaymiz: sozlama uch darajada yashaydi — system (butun kompyuter), global (sizning foydalanuvchingiz, ~/.gitconfig) va local (bitta repo, .git/config). Bir xil kalit bir necha joyda bo'lsa, yaqinrog'i yutadi: local → global → system.

Yangi Git versiyalarida git config ga aniq buyruqlar qo'shildi: get, set, list, unset. Eski shakl (git config user.email) ham ishlaydi, lekin yangisi o'qishga tushunarliroq. Git'ning o'z maslahatlari ham endi shu shaklda chiqadi — Jamoa workflow'lari darsidagi git config set advice.diverging false ni eslang.

bash
git config set alias.st "status -sb"
git config get alias.st
git config get --show-scope user.email
git config get nomalum.kalit; echo "exit $?"

Terminalda:

text
status -sb
global	aziz@example.com
exit 1

set jim ishladi (chiqish kodi 0). --show-scope qiymat oldiga darajani yozdi: email global sozlamadan kelyapti. Yo'q kalitda get hech narsa yozmaydi, faqat 1 qaytaradi — skriptda shunga tayanish mumkin.

2.2 Kim yutdi: --show-origin

Bitta kalit bir necha fayldan kelishi mumkin. Shunda --all hammasini, --show-origin esa fayl yo'lini ko'rsatadi. Bu buyruqni «includeIf» bo'limida ko'p ishlatamiz:

flowchart LR
  S["system<br/>(kompyuter)"] --> G["global<br/>~/.gitconfig"]
  G --> I["includeIf fayli<br/>(shart bajarilsa)"]
  I --> L["local<br/>.git/config"]
  L --> N["git config get<br/>oxirgisi yutadi"]

Diagrammani chapdan o'ngga o'qing. Git fayllarni shu tartibda o'qiydi, keyingisi oldingisini bosib o'tadi. includeIf fayli global faylning ichiga ulanadi — u global darajada, lekin o'zidan oldingi qatorlardan keyin turadi.

3. Alias: o'z buyruqlaringiz

3.1 Oddiy alias

Tarixni o'qish darsida git lg ni yaratgansiz. Alias — alias.<nom> sozlamasi: qiymati git dan keyingi so'zlar. Biz uchtasini yozdik:

bash
git config set alias.lg "log --oneline --graph --decorate -5"
git config set alias.oxirgi "log -1 --format='%h %an: %s'"
git st
git lg
git oxirgi
text
## main
* 88b1656 (HEAD -> main) feat: boshlang'ich
88b1656 Aziz Karimov: feat: boshlang'ich

git st — status -sb: qisqa holat va branch nomi bitta qatorda. git oxirgi — oxirgi commit qisqa ko'rinishda. Alias nimaga teng ekanini unutsangiz, Git o'zi aytadi:

bash
git help st
text
'st' is aliased to 'status -sb'

Hamma alias ro'yxati — git config get --all --show-names --regexp '^alias\.'.

3.2 ! bilan alias

Qiymat ! bilan boshlansa, Git uni shell buyrug'i sifatida ishga tushiradi. Shunda bir nechta buyruqni birlashtirish va argument olish mumkin:

bash
git config set alias.yangi \
  '!f() { git switch -c "$1" && git push -u origin "$1"; }; f'

git yangi docs/readme — branch ochadi va darhol yuboradi. f() { …; }; f — bash funksiyasi: $1 birinchi argument (Shell skript yozish asoslari darsi).

Diqqat: ! li alias — oddiy shell skript. Begona odam bergan .gitconfig ni ko'r-ko'rona nusxalamang: unda istalgan buyruq yashirinishi mumkin. Har alias'ni o'qib, tushunib qo'shing.

Alias'ni faqat buyruqni tushunganingizdan keyin yarating. Boshqa kompyuterda yoki hamkasb bilan ishlaganda to'liq buyruqni bilishingiz kerak bo'ladi.

4. includeIf: ish va shaxsiy akkaunt

4.1 Muammo

SSH kalit darsida ikki GitHub akkaunti uchun ikki kalit sozlagansiz va va'da bergan edik: har repoda alohida emailni avtomatlashtiramiz. Muammo shunday: global user.email — bitta. Ish repo'sida har safar git config user.email … yozishni unutasiz, va kompaniya tarixiga shaxsiy emailingiz tushadi.

Yechim — shartli qo'shish (includeIf): "repo shu papkada bo'lsa, mana bu faylni ham o'qi".

4.2 gitdir: — papka bo'yicha

Ish loyihalari ~/ish/ da, shaxsiylari boshqa joyda deylik. Global faylga bitta shart, ish uchun alohida fayl:

bash
git config --global includeIf."gitdir:~/ish/".path \
  "~/.gitconfig-ish"
git config --file ~/.gitconfig-ish \
  user.email "aziz@kompaniya.example.com"

--file — ixtiyoriy faylga yozish. Natijada ~/.gitconfig (bizning sinovdagi to'liq mazmuni):

text
[user]
	name = Aziz Karimov
	email = aziz@example.com
[init]
	defaultBranch = main
[core]
	autocrlf = false
[includeIf "gitdir:~/ish/"]
	path = ~/.gitconfig-ish

Endi ikki repo ochib, emailni so'raymiz:

bash
git init -q ~/ish/vazifalar-api
git init -q ~/shaxsiy/portfolio
for r in ish/vazifalar-api shaxsiy/portfolio; do
  echo "$r: $(git -C ~/$r config user.email)"
done
text
ish/vazifalar-api: aziz@kompaniya.example.com
shaxsiy/portfolio: aziz@example.com

git -C <papka> — buyruqni o'sha papkada bajarish (cd qilmasdan). Ish repo'si o'z emailini oldi. Nega? --show-origin ko'rsatadi (uy papkasi yo'li ~ ga qisqartirildi):

bash
git -C ~/ish/vazifalar-api config get --all --show-origin \
  user.email
text
file:~/.gitconfig	aziz@example.com
file:~/.gitconfig-ish	aziz@kompaniya.example.com

Ikkala qiymat ham bor. Ikkinchisi keyin o'qilgani uchun yutadi — «Kim yutdi» bo'limidagi diagramma aynan shu.

4.3 Ikki tuzoq: oxirgi / va katta harf

Biz shartni ikki xil "deyarli to'g'ri" yozib ko'rdik:

text
slash'siz: aziz@example.com
gitdir:~/ISH/   -> aziz@example.com
gitdir/i:~/ISH/ -> aziz@kompaniya.example.com
  1. Oxirgi / siz (gitdir:~/ish) — ishlamadi. Shart .git papkasining yo'liga qaraydi: u ~/ish/vazifalar-api/.git. Git hujjatiga ko'ra, naqsh / bilan tugasa, oxiriga ** qo'shiladi — "shu papka ichidagi hamma narsa". / siz naqsh faqat aniq shu yo'lga mos keladi.
  2. Katta harf (gitdir:~/ISH/) — ishlamadi. gitdir: katta-kichik harfni farqlaydi. Windows'da papka nomi Ish yoki ish bo'lishi mumkin, fayl tizimi ularni bir xil ko'radi, Git esa yo'q. gitdir/i: — harfga qaramaydigan shakl. Windows va macOS'da shuni yozing.

Ikkala holatda ham xato xabari chiqmadi — Git jim global emailni qo'ydi. Shuning uchun sozlagandan keyin doim ish papkasidagi repoda git config get --show-origin user.email bilan tekshiring.

4.4 hasconfig: — remote manzili bo'yicha

Ba'zan loyihalar papka bo'yicha emas, tashkilot bo'yicha ajraladi. Shart remote URL'iga ham qaray oladi:

bash
K='includeIf.hasconfig:remote.*.url:'
K+='https://github.com/kompaniya/**.path'
git config --global "$K" '~/.gitconfig-ish'

Biz ikki repo yaratib, ularga remote qo'shdik:

text
portfolio: aziz@example.com
boshqa/api: aziz@kompaniya.example.com

boshqa/api ish papkasida emas, lekin remote'i github.com/kompaniya/ da — ish emaili qo'yildi. Bu shart git clone dan keyin ishlaydi: remote qo'shilmagan yangi git init repo hali hech qaysi shartga mos emas.

Tekshirib ko'ring: includeIf "gitdir:~/ish/" ni global faylning boshiga, [user] email = aziz@example.com dan oldin yozdingiz. Ish repo'sida qaysi email chiqadi?

Javob

Shaxsiy email — aziz@example.com. Git faylni yuqoridan pastga o'qiydi va bir xil kalitda oxirgisi yutadi. Ulangan fayl o'z joyida o'qiladi: avval ish emaili, keyin pastdagi [user] uni bosib o'tadi. Shuning uchun includeIf qatorlari global faylning oxirida tursin. git config --global bilan qo'shsangiz, Git ularni o'zi oxiriga yozadi.

5. Kundalik tezlashtirgichlar

5.1 push.autoSetupRemote

Remote darsidan tanish xato — yangi branch'ning birinchi push'i:

bash
git switch -c feature/filtr
# ... commit
git push
text
fatal: The current branch feature/filtr has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin feature/filtr

To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.

"Joriy branch'ning upstream'i yo'q." Xabarning o'zi yechimni aytyapti — push.autoSetupRemote. Yoqamiz va xuddi shu git push:

bash
git config set push.autoSetupRemote true
git push
text
To ../server.git
 * [new branch]      feature/filtr -> feature/filtr
branch 'feature/filtr' set up to track 'origin/feature/filtr'.

Branch yuborildi va kuzatuv (tracking) o'zi sozlandi. Sinovda remote — lokal "bare" repo (../server.git), GitHub'da xuddi shunday ishlaydi. GitHub flow'da har ish yangi branch (Jamoa workflow'lari) — bu sozlama kuniga bir necha marta vaqt tejaydi.

5.2 fetch.prune

PR merge bo'lgach, branch serverda o'chiriladi. Lekin sizning kompyuteringizdagi origin/feature/filtr nusxasi qoladi. Biz Nodira nomidan serverdagi branch'ni o'chirdik, keyin Aziz git fetch qildi:

text
  origin/HEAD -> origin/main
  origin/feature/filtr
  origin/main

git fetch jim o'tdi, git branch -r esa o'lik branch'ni ko'rsatyapti. Bir necha oyda bunday "arvoh"lar o'nlab bo'ladi. fetch.prune bilan:

bash
git config set fetch.prune true
git fetch
text
From ../server
 - [deleted]         (none)     -> origin/feature/filtr

Serverda yo'q branch'ning lokal nusxasi o'chdi. Bu faqat origin/… ko'rsatkichlariga tegadi — sizning lokal branch'laringiz (feature/filtr) o'chmaydi. Ularni tozalash — Pull Request darsidagi git branch -d retsepti.

5.3 help.autocorrect

Buyruqni xato yozdingiz: git sttaus. Sukut bo'yicha Git taklif beradi va to'xtaydi:

text
git: 'sttaus' is not a git command. See 'git --help'.

The most similar command is
	status

help.autocorrect buni o'zgartiradi. Biz qiymatlarni sinadik, jadval Git 2.54 hujjati bilan ham solishtirildi. Tuzoqqa e'tibor bering: 1 "0.1 soniya" emas — hujjatga ko'ra u immediate bilan bir xil (biz sinadik: kutmasdan bajardi):

Qiymat Nima bo'ladi
0 yoki show (sukut) taklif ko'rsatadi, bajarmaydi
immediate yoki 1 darhol bajaradi
10 (1 dan katta son) 1.0 soniya kutib bajaradi (o'ndan bir soniyalarda)
never taklif ham ko'rsatmaydi
prompt "bajaraymi?" deb so'raydi

immediate dagi chiqish:

text
WARNING: You called a Git command named 'sttaus', which does not exist.
Continuing under the assumption that you meant 'status'.
On branch main
nothing to commit, working tree clean

"Mavjud bo'lmagan buyruqni chaqirdingiz. status demoqchi edingiz, deb davom etyapman." Qulay — lekin xavfli tomoni ham bor. Biz git comit -m "x" yozdik va Git uni so'ramasdan commit sifatida bajardi. Bu safar commit qiladigan narsa yo'q edi. Lekin xuddi shunday push yoki reset ham so'roqsiz ishga tushadi.

Tavsiya: prompt — Git taklifni aytadi va tasdiq kutadi. Bu rejimni terminalsiz (skriptda) sinadik: so'rash imkoni bo'lmagani uchun Git buyruqni bajarmadi. Terminaldagi so'rov ko'rinishini biz sinamadik (sinalmagan, 2026-11).

6. Konflikt va diff sozlamalari

6.1 merge.conflictstyle zdiff3

Conflictlarni yechish darsidagi belgilar bilan konflikt. Asl qator narx: 25000 edi; main da 28 000 ga, branch'da 30 000 ga o'zgardi. Sukut ko'rinish:

text
<<<<<<< HEAD
narx: 28000
=======
narx: 30000
>>>>>>> feature/narx
vaqt: 09:00

Qaysi biri to'g'ri? Bu ko'rinishdan bilib bo'lmaydi: ikkalasi ham asldan o'zgarganmi yoki biri eski qiymatmi — noma'lum. zdiff3 bilan:

bash
git config set merge.conflictstyle zdiff3
git merge feature/narx
text
<<<<<<< HEAD
narx: 28000
||||||| e2e0cc1
narx: 25000
=======
narx: 30000
>>>>>>> feature/narx
vaqt: 09:00

||||||| dan keyin — asos (ikki tarix ajralgan commit, e2e0cc1). Endi rasm aniq: ikkala tomon ham 25 000 ni o'zgartirgan. Bu — "biri eskirgan" emas, haqiqiy kelishmovchilik: kim haq ekanini odamdan so'rash kerak. zdiff3 dagi z — ikki tomonda bir xil bo'lgan qatorlarni konflikt hududidan chiqarib tashlaydi, blok kichikroq bo'ladi.

6.2 rerere — yechimni eslab qolish

Rerere — "reuse recorded resolution", ya'ni "yozib olingan yechimni qayta ishlat". Bir xil konfliktni ikkinchi marta yechmaslik uchun. Qachon kerak? Masalan, uzoq branch'ni rebase qilasiz, bekor qilasiz, keyin qaytadan qilasiz — har safar o'sha konflikt. Yoqamiz va konfliktni bir marta yechamiz:

bash
git config set rerere.enabled true
git merge feature/narx
# menyu.txt da 30000 ni qoldirdik
git add menyu.txt && git commit --no-edit
text
CONFLICT (content): Merge conflict in menyu.txt
Recorded preimage for 'menyu.txt'
Automatic merge failed; fix conflicts and then commit the result.
Recorded resolution for 'menyu.txt'.

Ikki yangi qator: "konflikt holati yozib olindi" va commitda "yechim yozib olindi". Endi merge'ni bekor qilib (git reset --hard HEAD~1), qaytadan merge qilamiz:

text
CONFLICT (content): Merge conflict in menyu.txt
Resolved 'menyu.txt' using previous resolution.
Automatic merge failed; fix conflicts and then commit the result.

"Oldingi yechim bilan hal qilindi." Fayl ichida — narx: 30000, belgilarsiz. Lekin git status --short hali UU menyu.txt deydi: rerere faylni tuzatdi, lekin git add ni sizga qoldirdi. Bu ataylab: avtomatik yechimni ko'zdan kechiring, keyin add. Avtomatik add kerak bo'lsa — rerere.autoUpdate true (Git hujjati).

6.3 diff.algorithm histogram

Diff — "nima o'zgardi" degan savolga javob. Bir xil o'zgarishni turli algoritm turlicha ko'rsatadi. Biz ikki funksiyaning o'rnini almashtirdik — boshqa hech narsa o'zgarmadi. Sukut algoritm (myers):

text
@@ -1,13 +1,13 @@
-function narx(son) {
+function vaqt(son) {
   if (son > 0) {
-    return son * 25000;
+    return son * 60;
   }
   return 0;
 }
 
-function vaqt(son) {
+function narx(son) {
   if (son > 0) {
-    return son * 60;
+    return son * 25000;
   }
   return 0;
 }

Bu diff'ni o'qisangiz, ikkala funksiya "tahrirlangan"dek ko'rinadi: nom va son o'zgargan. Aslida esa funksiyalar faqat joy almashgan. Histogram:

text
@@ -1,13 +1,13 @@
-function narx(son) {
-  if (son > 0) {
-    return son * 25000;
-  }
-  return 0;
-}
-
 function vaqt(son) {
   if (son > 0) {
     return son * 60;
   }
   return 0;
 }
+
+function narx(son) {
+  if (son > 0) {
+    return son * 25000;
+  }
+  return 0;
+}

Endi aniq: narx tepadan olindi va pastga qo'yildi, vaqt tegilmagan. Qator soni ko'proq, lekin ma'no to'g'ri. Myers } va return 0; kabi ko'p takrorlanadigan qatorlarni bir-biriga bog'lab yubordi. Histogram esa avval kam uchraydigan qatorlardan "langar" tanlaydi.

bash
git config --global diff.algorithm histogram

Bu sozlama git diff, git log -p, git show ga ta'sir qiladi. Review'da diff'ni hamkasbingiz o'qiydi — qanchalik aniq bo'lsa, shuncha tez tushunadi.

7. Katta repoda tezlik

7.1 Kanon tajribasi: git status

Katta repolar darsida klon hajmini o'rgangan edik. Endi kundalik buyruqlar tezligi. Kanon sun'iy repo yaratdi: 40 001 fayl, 2 001 commit, 300 ta kuzatilmagan fayl. git status ni har sozlamada 5 marta o'lchab, medianasini oldi. Faqat shu repo'ning local sozlamasi o'zgartirildi.

git status: 40 001 faylli repo (mediana, 5 o'lchov)
  • sukut95 ms
  • core.untrackedCache92 ms
  • + core.fsmonitor83 ms

Manba: IlmHamroh kanon tajribasi, 2026-11-04: Git 2.54.0.windows.1, bitta mashina, NTFS kesh issiq; nisbat muhim

  • core.untrackedCache — kuzatilmagan fayllar ro'yxatini keshlaydi: har safar hamma papkani qayta ko'rmaydi. 95 → 92 ms.
  • core.fsmonitor — fon jarayoni (daemon) fayl tizimidagi o'zgarishlarni kuzatadi. git status 40 ming faylni tekshirish o'rniga "nima o'zgardi?" deb so'raydi. 92 → 83 ms. Windows va macOS uchun Git'da o'rnatilgan daemon bor; kanon uni Windows'da sinadi va oxirida to'xtatdi (git fsmonitor--daemon stop).

Farq atigi 13 % — kutganimizdan kam. Sabab: bitta mashina, fayllar operatsion tizim keshida "issiq". Sovuq diskda va yuz minglab faylda farq kattaroq bo'lishi mumkin — lekin buni biz o'lchamadik. Xulosa halol: o'lchamasdan yoqmang. Avval time git status, keyin sozlama, keyin yana o'lchov.

Git'da bir nechta sozlamani birdaniga yoqadigan bayroq bor — feature.manyFiles. Git 2.54 hujjatiga ko'ra u core.untrackedCache, indeksning ixcham formatini (index.version=4) va indeksni tezroq yozishni (index.skipHash) yoqadi. Biz uni o'lchamadik (sinalmagan, 2026-11).

7.2 Commit-graph

Commit-graph — commitlar orasidagi bog'lanishlarni alohida faylda saqlaydigan indeks. Katta tarixda git log --graph ni tezlashtiradi. Kanon o'lchovi (2 000 commit, fayl 120 KB):

Buyruq commit-graph yo'q bor
git log --graph --oneline 136 ms 145 ms
git rev-list --count HEAD 72 ms 69 ms

Foyda ko'rinmadi — 2 000 commit uning uchun kichik. Yuz minglab commitli repolarda (Linux yadrosi kabi) farq katta bo'ladi deyiladi, lekin bu sinalmagan. Saboq o'sha: sozlama "tezlashtiradi" degan va'da emas, o'lchov bilan tasdiqlanadigan faraz.

7.3 git maintenance va bitta topilma

Vaqt o'tishi bilan .git ichida minglab mayda fayl to'planadi — alohida obyektlar (loose object) (Git ichkaridan darsi). Ularni pack faylga yig'ish — git gc yoki zamonaviy git maintenance run.

Kanon 40 203 ta alohida obyektli repoda to'liq ro'yxatni (gc, commit-graph, loose-objects, incremental-repack) ishga tushirdi. Natija: 580 soniya ichida tugamadi — vaqt chegarasi to'xtatdi. Windows'da har obyekt alohida fayl, antivirus har birini tekshiradi. Keyin faqat ikkita yengil vazifa: --task=loose-objects --task=commit-graph — 7.7 soniya.

Lekin natijada g'alati narsa bor edi: hamma obyekt pack'ga yig'ildi (in-pack: 46203), alohida fayllar esa o'chmadi (count hali 40 203), .git hajmi 63 MB dan 66 MB ga o'sdi. Xatomi? Biz kichik repoda (2 000 obyekt) takrorladik:

bash
git maintenance run --task=loose-objects
git maintenance run --task=loose-objects
text
oldin:      count: 2000 in-pack: 0 
1-yugurish: count: 2000 in-pack: 2000 
2-yugurish: count: 0 in-pack: 2000 

Xato emas — dizayn. Git hujjatiga ko'ra, loose-objects vazifasi ikki qadamda ishlaydi: avval allaqachon pack'da bor alohida obyektlarni o'chiradi, keyin qolganlarini yangi pack'ga yig'adi. Birinchi yugurishda pack'da hech narsa yo'q edi — faqat yig'di. Ikkinchisida o'chirdi. Shunday qilinishi parallel ishlayotgan boshqa git buyruqlarini buzmaslik uchun: obyekt hech qachon "yo'q" bo'lib qolmaydi.

git maintenance start bu vazifalarni fonda soatlik, kunlik va haftalik jadval bilan ishga tushiradi — Windows'da schtasks (Task Scheduler) orqali (Git hujjati). Bu tizim sozlamasi bo'lgani uchun kanon uni ishlatmadi (sinalmagan). O'z kompyuteringizda katta repo bo'lsa — urinib ko'ring, git maintenance stop bilan o'chiriladi.

8. Muharrirda: GitLens

Ko'p dasturchilar Git tarixini VS Code ichida ko'radi. GitLens — eng mashhur kengaytmalardan biri: har qator yonida "kim, qachon, qaysi commit" (inline blame), fayl tarixi, branch'lar grafigi. Bu Kod arxeologiyasi darsidagi git blame va git log -L ning grafik ko'rinishi — ichida o'sha buyruqlar ishlaydi.

Biz GitLens'ni sinamadik (sinalmagan, 2026-11). Uning ba'zi imkoniyatlari pullik obuna bilan. VS Code'ning o'zida ham Source Control paneli va "Timeline" bor — ular bepul.

Muhimi: kengaytma terminal buyruqlarining o'rnini bosmaydi. Serverda, CI'da yoki hamkasb kompyuterida faqat terminal bo'ladi.

9. Loyiha qadami: o'z sozlamangiz

Bu dars — tajriba darsi: vazifalar-api o'zgarmaydi, commit yo'q. Lekin o'z kompyuteringizning global sozlamasini yangilashni tavsiya qilamiz. Biz tajribada sinagan sozlamalar:

bash
git config --global push.autoSetupRemote true
git config --global fetch.prune true
git config --global merge.conflictstyle zdiff3
git config --global rerere.enabled true
git config --global diff.algorithm histogram
git config --global help.autocorrect prompt
git config --global alias.st "status -sb"
git config --global alias.lg \
  "log --oneline --graph --decorate -20"

Ishxona va shaxsiy loyihalaringiz bo'lsa — includeIf ni qo'shing (Windows'da gitdir/i:):

bash
git config --global includeIf."gitdir/i:~/ish/".path \
  "~/.gitconfig-ish"
git config --file ~/.gitconfig-ish user.email "ish@emailingiz"

Keyin tekshiruv: vazifalar-api papkasida git config get --show-origin user.email — kutgan emailingiz va kutgan faylingiz chiqsin. Global faylingizni Git'ni o'rnatish darsidagidek git config --global --edit bilan ochib, ko'zdan kechiring.

Hammasini birdaniga yoqish shart emas. Bittadan qo'shing va bir hafta ishlating: qaysi biri haqiqatan yordam berayotganini o'zingiz sezasiz.

10. Ko'p uchraydigan xatolar

10.1 includeIf jim ishlamaydi

Eng ko'p uchraydigan holat. Xato xabari yo'q, faqat noto'g'ri email. Uch sabab: naqsh oxirida / yo'q; Windows'da harf farqi (gitdir/i: kerak); includeIf fayl boshida turibdi va pastdagi [user] uni bosib o'tadi. Tekshirish yo'li bitta: ish repo'sida git config get --all --show-origin user.email.

10.2 Commit allaqachon noto'g'ri email bilan

includeIf faqat keyingi commitlarga ta'sir qiladi. Push qilinmagan oxirgi commitni tuzatish: git commit --amend --reset-author --no-edit (Xatoni tuzatish 1 darsidagi amend). Push qilinganini qayta yozish — Tarixni qayta yozish darsidagi ehtiyot choralari bilan.

10.3 Alias o'rnatilgan buyruq nomi bilan

git config set alias.status "status -sb" — Git uni e'tiborsiz qoldiradi: o'rnatilgan buyruq har doim alias'dan ustun. Alias'ga yangi nom bering (st).

10.4 autocorrect immediate noto'g'ri buyruqni bajardi

«help.autocorrect» bo'limidagi comit misoli. Davosi — prompt yoki sukut qiymat. Shoshilganda tezlik emas, xavfsizlik muhim.

10.5 rerere noto'g'ri yechimni eslab qoldi

Konfliktni xato yechib, keyin tuzatdingiz — rerere esa birinchisini eslab qolgan bo'lishi mumkin. Unutdirish: git rerere forget <fayl> (konflikt holatida) — biz sinadik, Git "Forgot resolution for 'menyu.txt'" deb javob berdi. Shuning uchun rerere git add ni sizga qoldiradi — natijani ko'rib tasdiqlang.

11. Mashqlar

Mashqlar kurs/mashqlar/32/08-sozlama/ 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

  • Yangi branch'ni birinchi git push dayoq kuzatuv bilan yuboradigan sozlama — push.
  • Serverda o'chirilgan branch'larning lokal nusxasini fetch da tozalaydigan sozlama — fetch.
  • Konfliktda asos versiyasini ham ko'rsatadigan uslub — merge.conflictstyle
  • Bir marta yechilgan konfliktni eslab qoladigan sozlama — rerere.
  • Windows'da harf farqiga qaramaydigan papka sharti — includeIf " :~/ish/"
Yechim
  • autoSetupRemote — --set-upstream ni har safar yozmaslik uchun.
  • prune — faqat origin/… ko'rsatkichlari o'chadi, lokal branch'lar qoladi.
  • zdiff3 — ||||||| dan keyin asl qator.
  • enabled — yechim .git/rr-cache da saqlanadi.
  • gitdir/i — i — "ignore case", harfga qaramaslik.

2-mashq (o'rta): qaysi qiymat yutdi?

golibniTop(qatorlar, kalit) funksiyasini yozing. Kirish — git config list --show-scope chiqishining qatorlari: daraja + tab + kalit=qiymat. Funksiya berilgan kalitning yutgan qiymatini, uning darajasini va bosib o'tilgan qiymatlar ro'yxatini qaytarsin. Kalit topilmasa — null. Ishora: oxirgi mos qator yutadi. Qatorni split("\t") bilan, kalit=qiymat ni birinchi = bo'yicha bo'ling — qiymat ichida ham = bo'lishi mumkin: indexOf va slice (Kesish, bo'lish va to'ldirish).

Yechim
js
function golibniTop(qatorlar, kalit) {
  const mos = [];
  for (const q of qatorlar) {
    const [daraja, juft] = q.split("\t");
    const i = juft.indexOf("=");
    if (juft.slice(0, i) === kalit) {
      mos.push({ daraja, qiymat: juft.slice(i + 1) });
    }
  }
  if (mos.length === 0) return null;
  const golib = mos.at(-1);
  const bosilgan = mos.slice(0, -1).map(
    (m) => `${m.daraja}: ${m.qiymat}`,
  );
  return { ...golib, bosilgan };
}

const qatorlar = [
  "global\tuser.name=Aziz Karimov",
  "global\tuser.email=aziz@example.com",
  "global\tuser.email=aziz@kompaniya.example.com",
  "global\talias.yangi=!f() { a=1; }; f",
  "local\tcore.bare=false",
];
console.log(golibniTop(qatorlar, "user.email"));
console.log(golibniTop(qatorlar, "alias.yangi").qiymat);
console.log(golibniTop(qatorlar, "pull.rebase"));

Konsolda:

text
{
  daraja: 'global',
  qiymat: 'aziz@kompaniya.example.com',
  bosilgan: [ 'global: aziz@example.com' ]
}
!f() { a=1; }; f
null

Ikkinchi email includeIf faylidan kelgan, lekin darajasi baribir global — «includeIf» bo'limidagi --show-scope chiqishi kabi. Alias qiymatidagi ikkinchi = buzilmadi, chunki faqat birinchisi bo'yicha bo'ldik. mos.at(-1) — oxirgi element.

3-mashq (qiyin): ikki papka, ikki email

Vaqtinchalik papkada butun sozlamani noldan quring. Uy papkasi (HOME) va global fayl shu papkaga qaratilsin — haqiqiy sozlamangizga tegmasin. Talablar: global email aziz@example.com; ~/ish/ ichidagi repolar uchun aziz@kompaniya.example.com (harfga qaramaydigan shart); oxirgi alias'i — %h %ae: %s formatida oxirgi commit. Keyin ish/api va shaxsiy/sayt repolarida bittadan commit qilib, git oxirgi ni chiqaring. Oxirida papkani o'chiring.

Ishora: export HOME=$PWD — shu sessiya uchun ~ shu papkaga ochiladi. SHA'lar darsdagidek chiqishi uchun sanani qotiring: GIT_AUTHOR_DATE va GIT_COMMITTER_DATE (Bisect darsidagi skriptlar kabi).

Yechim
bash
mkdir sozlama-sinov && cd sozlama-sinov
export HOME=$PWD
export GIT_CONFIG_GLOBAL=~/.gitconfig
git config --global user.name "Aziz Karimov"
git config --global user.email "aziz@example.com"
git config --global init.defaultBranch main
git config --global alias.oxirgi "log -1 --format='%h %ae: %s'"
git config --global includeIf."gitdir/i:~/ish/".path \
  "~/.gitconfig-ish"
git config --file ~/.gitconfig-ish \
  user.email "aziz@kompaniya.example.com"

export GIT_AUTHOR_DATE="2026-11-04T10:00:00+05:00"
export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
for r in ish/api shaxsiy/sayt; do
  git init -q ~/$r
  echo "# $r" > ~/$r/README.md
  git -C ~/$r add README.md
  git -C ~/$r commit -q -m "docs: README"
  echo "$r -> $(git -C ~/$r oxirgi)"
done
git -C ~/ish/api config get --show-scope user.email
cd .. && rm -rf sozlama-sinov

Biz ishga tushirdik:

text
ish/api -> 1c831bb aziz@kompaniya.example.com: docs: README
shaxsiy/sayt -> d96eb69 aziz@example.com: docs: README
global	aziz@kompaniya.example.com

Ikki repo — ikki email, bitta global fayl. GIT_CONFIG_GLOBAL ni ham qaratdik: aks holda ba'zi tizimlarda Git HOME dan boshqa joydagi faylni o'qishi mumkin. Haqiqiy kompyuteringizda export HOME=… qilmaysiz — ~ o'z uy papkangiz bo'ladi.

12. Real ishda

  • Qayerda uchraydi: tajribali dasturchilarning ~/.gitconfig fayli ko'pincha GitHub'dagi "dotfiles" repo'sida turadi va yangi kompyuterga bir buyruq bilan ko'chiriladi. Kompaniyaga kirganda birinchi kuni includeIf bilan ish emailini ajratish — yaxshi odat.
  • Katta repolar: monorepo ishlatadigan kompaniyalarda core.fsmonitor, git maintenance va sparse-checkout (Katta repolar) birga yoqiladi. Microsoft o'z katta repolari uchun Scalar degan vositani yaratgan va u Git tarkibiga kirgan — Git hujjatiga ko'ra scalar clone sparse-checkout va fon xizmatini birdaniga yoqadi (biz sinamadik).
  • Intervyu savollari: "Ish va shaxsiy loyihalarda turli email'ni qanday ajratasiz?", "git rerere nima?", "git status katta repoda sekin — nima qilasiz?"

Xulosa

  • Sozlama uch darajada; git config get --show-scope va --show-origin qiymat qayerdan kelganini ko'rsatadi, oxirgi o'qilgani yutadi.
  • Alias — qisqa buyruq; ! li alias — shell skript, begonasini o'qimasdan qo'shmang.
  • includeIf "gitdir/i:~/ish/" va hasconfig:remote.*.url: — ish emailini avtomatik qo'yadi; oxirgi / va harf farqi jim xato beradi.
  • push.autoSetupRemote, fetch.prune, zdiff3, rerere, histogram — kundalik ishni tezlashtiradi va aniqlashtiradi; autocorrect immediate — xavfli.
  • Katta repoda untrackedCache, fsmonitor, git maintenance — lekin avval o'lchang: kanonda 95 → 83 ms, commit-graph 2 000 commitda foyda bermadi.

Keyingi dars: Jamoadagi yangi loyihaga kirish — notanish kod bazasida birinchi hafta: arxitektura xaritasi, git log bilan tarixni o'qish va birinchi kichik vazifa.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Git konfiguratsiyasi: alias, includeIf, rerere va unumdorlik sozlamalari — IlmHamroh