Mundarija (37)
- Bu darsda
- 1. Nega bu kerak?
- 2. Muammoni o'z ko'zimiz bilan ko'ramiz
- 2.1 Tajriba
- 2.2 Ko'rinmas belgini ko'rish
- 3. core.autocrlf — eski yechim
- 3.1 Sizdagi qiymat
- 3.2 Uch qiymat
- 3.3 Nega bu yetarli emas?
- 4. .gitattributes — qoida repoda
- 4.1 Fayl tuzilishi
- 4.2 Asosiy qator: * text=auto eol=lf
- 4.3 Istisnolar
- 5. Mavjud repoda yoqish: git add --renormalize
- 5.1 CRLF allaqachon repoda
- 5.2 Qayta normalizatsiya
- 5.3 Ishchi papkani yangilash
- 6. «Bahor»ga .gitattributes
- 7. Binar fayllar va diff
- 7.1 binary va rasm diff'i
- 7.2 -diff — matn, lekin diff'siz
- 7.3 linguist-generated — GitHub uchun
- 8. .editorconfig bilan birga
- 9. Ko'p uchraydigan xatolar
- 9.1 .gitattributes yaratib, --renormalize ni unutish
- 9.2 Normalizatsiyani ish bilan aralashtirish
- 9.3 Rasmga binary yozmaslik
- 9.4 Yangi ogohlantirish: CRLF will be replaced by LF
- 9.5 core.autocrlf=false qilib "tuzatish"
- 10. Mashqlar
- 1-mashq (oson): ls-files --eol ni o'qing
- 2-mashq (o'rta): .gitattributes ni to'ldiring
- 3-mashq (qiyin): Malikaning shikoyati
- 4-mashq: Portfolio qadami — portfolio'ga .gitattributes
- 11. Real ishda
- Xulosa
- Manbalar
.gitattributes va qator oxirlari: CRLF va LF muammosini hal qilish
Qisqacha: Windows qator oxiriga CRLF, Linux va macOS esa LF qo'yadi. Bu farq "bitta so'z o'zgargan, lekin hamma qatorlar o'zgargan" degan diff'larni keltirib chiqaradi. Yechim — loyiha ildizidagi
.gitattributesfayli:* text=auto eol=lfqatori hamma matn fayllarini repoda ham, ishchi papkada ham LF qiladi. Mavjud repoda undan keyingit add --renormalize .qilinadi. Rasmlargabinarybelgisi qo'yiladi.
Bu darsda
LF will be replaced by CRLFogohlantirishining sababini oxirigacha tushuntirasiz.core.autocrlfning uch qiymatini va uning kamchiligini bilasiz..gitattributesyozasiz:text=auto,eol=lf,binary,-diff,linguist-generated.git ls-files --eolbilan har faylning qator oxirini tekshirasiz vagit add --renormalizebilan reponi tozalaysiz..editorconfigva.gitattributesqanday birga ishlashini bilasiz.
Oldin bilishingiz kerak: Qator oxiri: CRLF va LF, .gitignore, HEAD va refs.
1. Nega bu kerak?
07-qism boshidan beri deyarli har git add da bir xil qator chiqib turibdi:
warning: in the working copy of 'index.html', LF will be replaced by CRLF the next time Git touches itBirinchi repo darsida "qo'rqmang, bu ogohlantirish, keyin tartibga solamiz" degan edik. Qator oxiri darsida esa .gitattributes faylini birinchi marta ko'rgan edik va "batafsil — Git qismida" deb va'da bergandik. Bugun ikkala va'dani bajaramiz.
Ogohlantirish — muammoning faqat ko'rinadigan uchi. Asl xavf jamoada chiqadi. Qator oxiri darsidagi voqeani eslang: Ali Windows'da bitta so'zni tuzatadi, Malika esa macOS'da hamma qatorlar o'zgarganini ko'radi. Bunday diff'ni hech kim o'qiy olmaydi. Hamkasb kodingizni tekshirganda (code review — buni qism oxirida o'rganamiz) haqiqiy o'zgarish yuzlab "soxta" o'zgarish ichida yo'qoladi. Serverda esa CRLF'li skript $'\r': command not found deb yiqiladi.
Bu dars — bir martalik sozlash. To'g'ri qilsangiz, loyiha umri davomida bu mavzuga qaytmaysiz.
2. Muammoni o'z ko'zimiz bilan ko'ramiz
2.1 Tajriba
Tajribani kurs/sinov-git/ ichidagi yangi repoda qilamiz. Malika Linux'da menyu sahifasini commit qilgan deb tasavvur qilamiz — fayl LF bilan. Aziz esa Windows'da ishlaydi va uning Git'ida avtomatik almashtirish o'chirilgan: git config core.autocrlf false (bu nima ekanini keyingi bo'limda ko'ramiz).
Takrorlamoqchi bo'lsangiz, tayyorgarlik shunday. printf — echo ning aniqroq varianti, \n ni LF'ga aylantiradi (Git ichkaridan darsida ishlatgansiz):
cd ~/kurs/sinov-git
mkdir qator && cd qator
git init
git config core.autocrlf false
printf '<h1>Menyu</h1>\n' > menyu.html
printf "<p>Osh — 35 000 so'm</p>\n" >> menyu.html
printf "<p>Choy — 3 000 so'm</p>\n" >> menyu.html
git add menyu.html
git commit -m "Menyu: sahifa yarat"git config --global siz — faqat shu repo uchun (Git'ni sozlash). Har faylning qator oxirini Git'ning o'zi ko'rsatadi:
git ls-files --eoli/lf w/lf attr/ menyu.htmlBu buyruq — bugungi darsning asosiy asbobi. Uch ustun:
| Ustun | Ma'nosi |
|---|---|
i/… |
Index (quti va repo) dagi nusxa: lf, crlf, mixed yoki -text (binar) |
w/… |
Ishchi papkadagi (working tree) nusxa |
attr/… |
.gitattributes dan kelgan qoida (hozir bo'sh) |
Hozir ikkala nusxa ham LF. Aziz choy narxini 3 000 dan 4 000 ga o'zgartirdi. Uning muharriri faylni CRLF bilan saqladi. Buni ikki buyruq bilan taqlid qilamiz: sed -i — faylda almashtirish, unix2dos — Qator oxiri darsidagi dos2unix ning teskarisi, LF'ni CRLF qiladi:
sed -i 's/Choy — 3 000/Choy — 4 000/' menyu.html
unix2dos -q menyu.html
file menyu.html
git diff --statmenyu.html: Unicode text, UTF-8 text, with CRLF line terminators
menyu.html | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)file buyrug'i (Qator oxiri darsidan) CRLF'ni ko'rsatdi. Bitta narx o'zgardi, Git esa "3 qator o'chdi, 3 qator qo'shildi" deyapti. Diff'ning o'zi:
@@ -1,3 +1,3 @@
-<h1>Menyu</h1>
-<p>Osh — 35 000 so'm</p>
-<p>Choy — 3 000 so'm</p>
+<h1>Menyu</h1>
+<p>Osh — 35 000 so'm</p>
+<p>Choy — 4 000 so'm</p>(Diff boshidagi diff --git va index qatorlarini qisqartirdik.) Ikki qator ko'zga mutlaqo bir xil. Farq ko'rinmas belgida — \r da.
2.2 Ko'rinmas belgini ko'rish
cat -A barcha ko'rinmas belgilarni ko'rsatadi: qator oxiri — $, \r — ^M:
git diff | cat -ANatijaning oxirgi qismi (ko'rsatilgan uch qator):
-<h1>Menyu</h1>$
-<p>Osh M-bM-^@M-^T 35 000 so'm</p>$
-<p>Choy M-bM-^@M-^T 3 000 so'm</p>$
+<h1>Menyu</h1>^M$
+<p>Osh M-bM-^@M-^T 35 000 so'm</p>^M$
+<p>Choy M-bM-^@M-^T 4 000 so'm</p>^M$Yangi qatorlar oxirida ^M bor. M-bM-^@M-^T — uzun tire (—) ning baytlari, cat -A harf bo'lmagan belgilarni shunday yozadi. Endi ls-files:
i/lf w/crlf attr/ menyu.htmlRepoda LF, ishchi papkada CRLF. Git ular farqli deb hisoblaydi — va haqli.
Diff'ni o'qish uchun vaqtinchalik yo'l bor — --ignore-cr-at-eol ("qator oxiridagi CR'ga e'tibor berma"):
git diff --ignore-cr-at-eol --stat menyu.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)Endi faqat bitta haqiqiy o'zgarish. Lekin bu faqat ko'rish uchun: commit qilinsa, CRLF baribir repoga tushadi va Malikaning faylida hamma qatorlar o'zgaradi. Muammoni ildizidan hal qilish kerak.
Tekshirib ko'ring:
git ls-files --eolnatijasii/lf w/crlf. Bu nimani anglatadi?
Javob
Repodagi (index) nusxada qator oxirlari LF, kompyuteringizdagi fayl esa CRLF. Commit qilganda nima bo'lishi sozlamaga bog'liq: almashtirish yoqilgan bo'lsa, Git CRLF'ni LF'ga aylantiradi; o'chirilgan bo'lsa — CRLF repoga tushadi.
3. core.autocrlf — eski yechim
3.1 Sizdagi qiymat
Git for Windows o'rnatuvchisi bu muammoni oldindan biladi va bitta sozlama qo'yadi. Git'ni sozlash darsida ro'yxatda ko'rgan edik. Qayerdan kelganini tekshiramiz:
git config --show-origin core.autocrlffile:D:/Dasturlash/Install/Git/etc/gitconfig trueSystem darajasi, qiymat true. (Bizda Git D: diskda. Odatiy o'rnatishda yo'l C:/Program Files/Git/etc/gitconfig bo'ladi.)
3.2 Uch qiymat
| Qiymat | git add da |
Fayl chiqarilganda |
|---|---|---|
true |
CRLF → LF | LF → CRLF |
input |
CRLF → LF | o'zgartirmaydi |
false |
o'zgartirmaydi | o'zgartirmaydi |
true — Windows uchun: repoda LF saqlanadi, sizga esa CRLF beriladi. input — macOS va Linux uchun: tasodifan kirib qolgan CRLF repoga tushmaydi. false — hech narsa qilmaydi.
Endi 07-qismdagi ogohlantirish to'liq tushunarli. Siz echo bilan LF fayl yaratdingiz. core.autocrlf=true bilan Git aytmoqda: "Repoga LF saqlayman. Lekin keyingi safar bu faylni ishchi papkaga chiqarganimda (checkout, restore, reset), CRLF bilan chiqaraman — fayl o'zgaradi, sizni ogohlantirib qo'yay". Sinovda aynan shunday bo'ldi — yangi reponing fayli Git chiqargandan keyin:
i/lf w/crlf attr/ a.txt3.3 Nega bu yetarli emas?
core.autocrlf — shaxsiy sozlama. U har kimning kompyuterida alohida turadi va repo bilan birga yurmaydi:
- Jamoaga yangi odam keldi. Git'ni boshqa usulda o'rnatgan — unda
false. U CRLF commit qiladi. - Kimdir "bu ogohlantirishlar jonga tegdi" deb
falseqilib qo'ydi. - macOS'dagi hamkasbda umuman sozlanmagan.
Bitta odam xato qilsa — butun jamoaning diff'i buziladi. Qoida hamma uchun bir xil bo'lishi uchun u repoda turishi kerak. Bu — .gitattributes.
4. .gitattributes — qoida repoda
4.1 Fayl tuzilishi
.gitattributes — loyiha ildizida turadigan matn fayli. Unda fayllarga "atribut" (xususiyat) beriladi: bu fayl matnmi, qator oxiri qanday bo'lsin, diff ko'rsatilsinmi. Tuzilishi .gitignore ga o'xshaydi: har qatorda shablon (pattern) va atributlar.
shablon atribut1 atribut2 ...Shablonlar .gitignore dagidek: * — hamma fayl, *.png — hamma PNG, sayt/*.html — sayt ichidagi HTML'lar. Bir fayl bir necha qatorga mos kelsa — pastdagi qator ustun.
Atribut uch holatda bo'ladi:
| Yozuv | Holat | Masalan |
|---|---|---|
text |
yoqilgan (set) | "bu matn fayl" |
-text |
o'chirilgan (unset) | "bu matn emas" |
eol=lf |
qiymat berilgan | "qator oxiri LF" |
4.2 Asosiy qator: * text=auto eol=lf
Qator oxiri darsida ko'rgan qator — eng muhimi:
*— barcha fayllar uchun.text=auto— "matnmi yoki binarmi, Git o'zi aniqlasin". Matn fayllarning qator oxirlari repoda doim LF'ga keltiriladi (normalizatsiya). Binar fayllarga tegilmaydi.eol=lf— ishchi papkaga chiqarganda ham LF. Ya'ni Windows'da ham fayllaringiz LF bo'ladi.
Normalizatsiya (normalization) — hamma narsani bitta standart ko'rinishga keltirish. Bu yerda — hamma qator oxirlarini LF'ga.
Nega Windows'da ham LF? Chunki zamonaviy muharrirlar — VS Code, Notepad, WebStorm — LF fayllarni muammosiz ochadi va saqlaydi. Loyiha esa oxir-oqibat Linux serverda ishlaydi. Hamma joyda LF — eng sodda va ishonchli tanlov.
.gitattributes va core.autocrlf to'qnashsa, .gitattributes ustun: text/eol atributi bor fayllar uchun Git core.autocrlf ga qaramaydi. Shuning uchun system sozlamangizni o'zgartirish shart emas.
4.3 Istisnolar
Ba'zi fayllarga boshqa qoida kerak:
* text=auto eol=lf
*.bat text eol=crlf
*.png binary*.bat text eol=crlf— Windows buyruq fayllari (.bat,.cmd) faqat Windows'da ishlaydi va CRLF talab qiladi.text— "bu albatta matn",eol=crlf— ishchi papkada CRLF. Repoda baribir LF saqlanadi.*.png binary— "bu matn emas, ichiga umuman tegma". Rasm baytlari orasida tasodifan 13 va 10 raqamlari bo'lishi mumkin — bular CR va LF belgilarining raqamlari. Git ularni almashtirsa, rasm buziladi.
binary — aslida uch atributning qisqa yozuvi. git check-attr buni ko'rsatadi:
git check-attr -a assets/images/choy.pngassets/images/choy.png: binary: set
assets/images/choy.png: diff: unset
assets/images/choy.png: merge: unset
assets/images/choy.png: text: unset
assets/images/choy.png: eol: lf-text (qator oxiriga tegma), -diff (matn diff'ini ko'rsatma) va -merge (qatorma-qator birlashtirma). eol: lf qatori * qoidasidan kelgan, lekin text o'chirilgani uchun unga e'tibor berilmaydi. git check-attr — "bu faylga qaysi qoidalar ta'sir qilyapti?" degan savolning javobi.
Tekshirib ko'ring:
.gitattributesda* text=auto eol=lfva undan pastda*.bat text eol=crlfyozilgan.ishga-tushir.batfayli ishchi papkada qanday qator oxiri bilan chiqadi?
Javob
CRLF bilan. Ikkala qator ham .bat faylga mos keladi, lekin pastdagi qator ustun. Repoda esa u baribir LF saqlanadi — text atributi normalizatsiya qiladi. Sinovimizda git check-attr -a ishga-tushir.bat shunday dedi: text: set, eol: crlf.
5. Mavjud repoda yoqish: git add --renormalize
5.1 CRLF allaqachon repoda
Eng og'ir holat: kimdir core.autocrlf=false bilan CRLF fayllarni commit qilib bo'lgan. Sinov reposimizga shunday CSS va .bat fayl qo'shamiz. \r\n — aynan CRLF:
printf 'body { margin: 0; }\r\n' > asosiy.css
printf 'h1 { color: green; }\r\n' >> asosiy.css
printf '@echo off\r\necho Salom\r\n' > ishga-tushir.bat
git add asosiy.css ishga-tushir.bat
git commit -m "Sinov: CSS va bat faylni CRLF bilan qo'sh"git ls-files --eol natijasi:
i/crlf w/crlf attr/ asosiy.css
i/crlf w/crlf attr/ ishga-tushir.bat
i/lf w/lf attr/ menyu.htmli/crlf — CRLF repoga tushib qolgan. Endi .gitattributes yaratamiz (yuqoridagi uch qator) va qaraymiz:
git ls-files --eoli/crlf w/crlf attr/text=auto eol=lf asosiy.css
i/crlf w/crlf attr/text eol=crlf ishga-tushir.bat
i/lf w/lf attr/text=auto eol=lf menyu.htmlattr ustuni to'ldi — qoidalar ishlayapti. Lekin i/crlf o'zgarmadi. .gitattributes faqat keyingi git add larga ta'sir qiladi. Repoda allaqachon turgan fayllarni o'zi qayta yozmaydi.
5.2 Qayta normalizatsiya
Buning uchun maxsus flag bor. Rasmiy Git hujjatidagi tartib — toza ishchi papkadan:
git add --renormalize .
git status -sM asosiy.css
M ishga-tushir.bat
?? .gitattributes--renormalize — "kuzatilayotgan hamma fayllarni yangi qoidalar bilan qaytadan qutiga sol". Ikki fayl M bo'ldi — ularning repodagi nusxasi o'zgaradi. menyu.html ro'yxatda yo'q, u allaqachon LF edi. Tekshiramiz:
i/lf w/crlf attr/text=auto eol=lf asosiy.css
i/lf w/crlf attr/text eol=crlf ishga-tushir.bat
i/lf w/lf attr/text=auto eol=lf menyu.htmlQuti endi hamma joyda i/lf. Hammasini alohida commit qilamiz — .gitattributes bilan birga:
git add .gitattributes
git commit -m "Git: qator oxirlarini LF ga keltir"Bizning sinovda .gitattributes ni git add --renormalize dan oldin qo'shmagan edik, shuning uchun commit ikki faylni ko'rsatdi:
[main 9358a82] Git: qator oxirlarini LF ga keltir
2 files changed, 4 insertions(+), 4 deletions(-)Nega alohida commit? Bu commit har faylning har qatorini "o'zgartiradi". Uni haqiqiy o'zgarish bilan aralashtirsangiz, diff'da haqiqiy ish yo'qoladi. Alohida, aniq nomli commit esa tarixda "bu yerda faqat qator oxirlari o'zgargan" deb turadi. Kod arxeologiyasi darsida bunday commitni git blame dan yashirishni ham o'rganamiz.
5.3 Ishchi papkani yangilash
Repo toza, lekin kompyuterdagi fayllar hali w/crlf. Git ularni keyingi safar faylga tekkanda LF bilan chiqaradi. Bitta faylni hozir yangilash uchun uni o'chirib, qayta chiqarish kifoya:
rm asosiy.css
git checkout -- asosiy.css
file asosiy.cssasosiy.css: ASCII textwith CRLF line terminators qismi yo'q — fayl endi LF. (Bu yerda git restore asosiy.css ham xuddi shunday ishlaydi.)
Butun loyihani birdan yangilash uchun ikki buyruq bor. «Bahor»da ko'rsatamiz.
6. «Bahor»ga .gitattributes
«Bahor» reposini Birinchi repo darsi oxiridagi holatdan olamiz. Windows'dagi odatiy holat — Git fayllarni bir necha marta chiqargan (Reset darsidagi reset --hard kabi) va ular CRLF bo'lib qolgan:
i/lf w/crlf attr/ aloqa/index.html
i/lf w/crlf attr/ assets/css/asosiy.css
i/lf w/crlf attr/ bron/index.html
i/lf w/crlf attr/ bron/rahmat.html
i/lf w/crlf attr/ index.html
i/lf w/crlf attr/ menyu/index.htmlRepo toza (i/lf) — core.autocrlf=true bunga g'amxo'rlik qilgan. Lekin muammo boshqa joyda. Menyuga echo bilan qator qo'shamiz:
echo "<p>Somsa — 8 000 so'm</p>" >> menyu/index.html
git add menyu/index.html
git ls-files --eol menyu/index.htmlwarning: in the working copy of 'menyu/index.html', LF will be replaced by CRLF the next time Git touches it
i/lf w/mixed attr/ menyu/index.htmlw/mixed — aralash! Eski qatorlar CRLF, echo qo'shgan yangi qator LF. Bitta faylda ikki xil qator oxiri. Ogohlantirishning asl sababi mana shu.
(Bu qo'shimchani bekor qildik.) Endi «Bahor» uchun to'liq .gitattributes yozamiz. VS Code'da loyiha ildizida yangi fayl oching:
# Matn fayllari: repoda ham, ishchi papkada ham LF
* text=auto eol=lf
# Faqat Windows'da ishlaydigan skriptlar: CRLF
*.bat text eol=crlf
*.cmd text eol=crlf
# Rasmlar va shriftlar: ichiga tegilmasin
*.png binary
*.jpg binary
*.webp binary
*.woff2 binary# bilan boshlangan qatorlar — izoh, .gitignore dagi kabi. Hozir «Bahor»da rasm yo'q, lekin bu qoidalar oldindan turgani yaxshi. .woff2 — veb-shrift fayli (Web shriftlar darsida ishlatgansiz).
Tartib — rasmiy hujjatdagidek:
git add --renormalize .
git status -s?? .gitattributesRepo allaqachon LF edi — qayta normalizatsiya qiladigan narsa yo'q. Faqat yangi fayl. Commit qilamiz:
git add .gitattributes
git commit -m "Git: qator oxirlarini .gitattributes bilan tartibla"[main f54f018] Git: qator oxirlarini .gitattributes bilan tartibla
1 file changed, 12 insertions(+)
create mode 100644 .gitattributesIshchi papka hali w/crlf. Git status da buni o'zgarish deb ko'rsatmaydi — mazmun bir xil. Endi hammasini birdan LF bilan qayta chiqaramiz. Bu ikki buyruq faqat toza ishchi papkada xavfsiz:
git status
git rm -r --cached -q .
git reset --hardOn branch main
nothing to commit, working tree clean
HEAD is now at f54f018 Git: qator oxirlarini .gitattributes bilan tartiblaBirinchisi — tekshiruv: working tree clean. git rm -r --cached -q . — hamma faylni qutidan oladi (diskdagi fayllarga tegmaydi). git reset --hard — qutini va ishchi papkani oxirgi commitdan qayta to'ldiradi. Endi fayllar yangi qoida bilan chiqdi:
git ls-files --eoli/lf w/lf attr/text=auto eol=lf .gitattributes
i/lf w/lf attr/text=auto eol=lf aloqa/index.html
i/lf w/lf attr/text=auto eol=lf assets/css/asosiy.css
i/lf w/lf attr/text=auto eol=lf bron/index.html
i/lf w/lf attr/text=auto eol=lf bron/rahmat.html
i/lf w/lf attr/text=auto eol=lf index.html
i/lf w/lf attr/text=auto eol=lf menyu/index.htmlHamma joyda LF. Endi o'sha somsa qatorini qayta qo'shamiz:
echo "<p>Somsa — 8 000 so'm</p>" >> menyu/index.html
git add menyu/index.html
git commit -m "Menyu: somsa narxini qo'sh"[main 56b3259] Menyu: somsa narxini qo'sh
1 file changed, 1 insertion(+)git add jim qoldi — ogohlantirish yo'q! 07-qism boshidan beri chiqib turgan qator yo'qoldi. Fayl LF, qoida LF — almashtiradigan narsa yo'q.
Diqqat:
git reset --hardcommit qilinmagan ishni o'chiradi (Reset darsi). Ishchi papkani yangilashdan oldin doimgit status—working tree cleanbo'lishi shart. Shoshilmasangiz, bu qadam umuman majburiy emas: fayllar vaqt o'tib, Git ularga tekkanda o'zi LF bo'ladi.
7. Binar fayllar va diff
7.1 binary va rasm diff'i
«Bahor»ga kichik PNG fayl qo'shdik (sinov uchun bir necha baytli) va keyin uni o'zgartirdik:
git diff
git diff --statdiff --git a/assets/images/choy.png b/assets/images/choy.png
index b437676..a80ba77 100644
Binary files a/assets/images/choy.png and b/assets/images/choy.png differ
assets/images/choy.png | Bin 20 -> 20 bytes
1 file changed, 0 insertions(+), 0 deletions(-)Tarjimasi: "choy.png ning binar fayllari farq qiladi". Git rasmning ichini qatorma-qator ko'rsatishga urinmaydi — ma'nosi yo'q. --stat da Bin — binar, hajmi ko'rsatiladi. git ls-files --eol da esa i/-text w/-text — "matn emas".
Git ko'pincha binar faylni binary qoidasisiz ham taniydi — ichida nol bayt bo'lsa. Lekin qoida yozish ishonchliroq: ba'zi binar fayllar "matnga o'xshab" qolishi mumkin.
7.2 -diff — matn, lekin diff'siz
Ba'zi fayllar matn, lekin ularning diff'i hech kimga kerak emas. Eng mashhur misol — package-lock.json. U npm install da avtomatik yoziladi va bitta paket yangilanganda yuzlab qator o'zgaradi. Portfolio'da:
package-lock.json -diffEndi fayl o'zgarganda:
diff --git a/package-lock.json b/package-lock.json
index e9065a1..9cafbc5 100644
Binary files a/package-lock.json and b/package-lock.json differGit uni "binar" deb ko'rsatdi — lekin faqat diff'da. Qator oxirlari esa text=auto bo'yicha normalizatsiya qilinaveradi, fayl commitga tushadi. -diff faqat "bu faylning ichini diff'da ochma" degani.
Maslahat:
-diffni ehtiyot bilan ishlating.package-lock.jsono'zgarishini ba'zan ko'rish kerak bo'ladi (qaysi paket versiyasi o'zgardi?). Bunday paytdagit diff --text package-lock.jsonbaribir to'liq diff'ni chiqaradi.
7.3 linguist-generated — GitHub uchun
Ba'zi atributlarni Git emas, GitHub o'qiydi. docs.github.com ga ko'ra, linguist-generated belgili fayllar:
- Pull Request (o'zgarishingizni loyihaga qo'shishni so'raydigan GitHub sahifasi) diff'larida odatiy holatda yashiriladi;
- repo tilini hisoblashda (sahifadagi "HTML 60%, CSS 40%" kabi statistika) hisobga olinmaydi.
package-lock.json linguist-generatedBu avtomatik yaratilgan fayllar (lock fayllar, yig'ilgan kod) uchun. Pull Request'larni shu qismda o'rganamiz — o'shanda bu qatorning foydasini ko'rasiz.
8. .editorconfig bilan birga
VS Code sozlamalari darsida .editorconfig ni ko'rgan edik. Unda ham qator oxiri bor:
[*]
end_of_line = lfIkkalasi bir ishni qilyaptimi? Yo'q, ular ikki xil joyda ishlaydi:
flowchart LR
E[".editorconfig<br/>muharrir"] --> F["Diskdagi fayl"]
F --> G[".gitattributes<br/>git add"]
G --> R[("Repo: LF")]
R --> G2[".gitattributes<br/>checkout"]
G2 --> FNimaga qarang: .editorconfig — muharrirga "yangi faylni LF bilan yoz" deydi (VS Code'da kengaytma kerak). .gitattributes esa Git'ning kirish va chiqish eshigida turadi: repoga nima tushishini va diskka nima chiqishini belgilaydi. Muharrir xato qilsa, Git tuzatadi. Git'dan tashqarida (masalan, fayl nusxalanganda) esa muharrir qoidasi yordam beradi.
Yaxshi loyihada ikkalasi ham bor va ikkalasida ham LF.
9. Ko'p uchraydigan xatolar
9.1 .gitattributes yaratib, --renormalize ni unutish
Qoida yozildi, lekin repodagi eski CRLF fayllar i/crlf bo'lib qoldi. Ular keyingi safar kimdir tahrirlaganda "hamma qator o'zgargan" ko'rinishida chiqadi. .gitattributes qo'shgandan keyin — har doim git add --renormalize . va git ls-files --eol bilan tekshiruv.
9.2 Normalizatsiyani ish bilan aralashtirish
"Qator oxirlari" commitiga haqiqiy o'zgarish ham qo'shilsa, u yuzlab soxta o'zgarish ichida ko'rinmay qoladi. Normalizatsiya — alohida commit.
9.3 Rasmga binary yozmaslik
* text=auto odatda rasmni taniydi. Lekin * text (auto'siz) yozsangiz, Git hamma faylni matn deb hisoblaydi va rasm baytlarini "tuzatib" buzadi. Rasm va shriftlar uchun binary qatorini doim yozing.
9.4 Yangi ogohlantirish: CRLF will be replaced by LF
.gitattributes dan keyin teskari ogohlantirishni ko'rishingiz mumkin:
warning: in the working copy of 'bron.html', CRLF will be replaced by LF the next time Git touches itTarjimasi: "bron.html ning ishchi nusxasidagi CRLF, Git keyingi safar unga tegganda, LF bilan almashtiriladi". Bu yaxshi belgi: qoida ishlayapti. Muharriringiz faylni CRLF bilan saqlagan — repoga baribir LF tushadi. Muharrirni ham LF'ga sozlang: VS Code'ning pastki o'ng burchagidagi CRLF yozuvini bosing (Qator oxiri darsidan) yoki .editorconfig qo'shing.
9.5 core.autocrlf=false qilib "tuzatish"
Ogohlantirishdan qutulish uchun sozlamani o'chirish — noto'g'ri yo'l. Ogohlantirish yo'qoladi, lekin CRLF repoga tusha boshlaydi. To'g'ri yo'l — .gitattributes.
10. Mashqlar
1-mashq (oson): ls-files --eol ni o'qing
Sinov reposidagi .gitattributes da faqat ikki qator bor: *.html text=auto eol=lf va *.png binary. git ls-files --eol natijasi:
i/crlf w/crlf attr/ eski.css
i/lf w/lf attr/text=auto eol=lf index.html
i/-text w/-text attr/-text logo.png
i/lf w/mixed attr/text=auto eol=lf menyu.htmlHar qator nimani anglatadi va qaysi biri muammo?
Ishora: «Tajriba» bo'limidagi ustunlar jadvali.
Yechim
eski.css— muammo: CRLF repoga tushgan va CSS uchun qoida yo'q (attr/bo'sh)..gitattributesga* text=auto eol=lfqatorini qo'shib,git add --renormalize .qilish kerak.index.html— ideal: repoda va diskda LF, qoida bor.logo.png— to'g'ri: binar, qator oxiriga tegilmaydi.menyu.html— muammo: repoda LF va qoida bor, lekin diskdagi faylda aralash qator oxirlari (muharrir CRLF qator qo'shgan). Faylni muharrirda LF qilib saqlash kerak — keyingigit addda repoga baribir LF tushadi.
2-mashq (o'rta): .gitattributes ni to'ldiring
Loyihada HTML, CSS, deploy.sh (Linux serverda ishlaydi), build.bat (faqat Windows) va .jpg rasmlar bor. Bo'sh joylarni to'ldiring:
* text= eol=
*.bat text eol=
*.jpg deploy.sh uchun alohida qator kerakmi? Javob: (birinchi qator uni allaqachon LF qiladi).
Ishora: «Istisnolar» bo'limi — .bat va rasmlar.
Yechim
* text=auto eol=lf
*.bat text eol=crlf
*.jpg binarydeploy.sh birinchi qatorga mos keladi va LF bo'ladi — Linux serverga kerakli narsa. Ko'p loyihalarda baribir *.sh text eol=lf qatori aniqlik uchun yoziladi: kimdir birinchi qatorni o'zgartirsa ham, skriptlar buzilmaydi.
3-mashq (qiyin): Malikaning shikoyati
Malika (macOS) aytdi: "Aziz har commitda butun aloqa/index.html ni o'zgartiryapti, diff'da hamma qator qizil-yashil". Aziz'ning kompyuterida git config core.autocrlf buyrug'i false deb javob berdi, git ls-files --eol aloqa/index.html esa shuni:
i/crlf w/crlf attr/ aloqa/index.html- Muammoning sababi nima?
- Aziz sozlamasini
trueqilsa, bu yetarlimi? Nega? - Butun jamoa uchun to'g'ri yechim — qaysi buyruqlar, qaysi tartibda?
Ishora: «core.autocrlf — eski yechim» va «Mavjud repoda yoqish» bo'limlari.
Yechim
- Aziz'da almashtirish o'chiq (
false), muharriri CRLF yozadi — va CRLF repoga tushib qolgan (i/crlf). Malika faylni LF bilan saqlaganda, hamma qator "o'zgaradi" va aksincha. - Yetarli emas. U faqat Aziz'ning keyingi commitlarini tuzatadi. Repodagi
i/crlfo'z joyida qoladi. Keyingi yangi hamkasb yanafalsebilan kelishi mumkin — shaxsiy sozlama hech kimni majburlamaydi. - Repoda qoida va bir martalik normalizatsiya:
git status
echo '* text=auto eol=lf' > .gitattributes
git add --renormalize .
git add .gitattributes
git status -s
git commit -m "Git: qator oxirlarini .gitattributes bilan tartibla"
git ls-files --eolOxirida hamma qator i/lf. Endi hech kimning core.autocrlf qiymati muhim emas — qoida repo bilan birga yuradi.
4-mashq: Portfolio qadami — portfolio'ga .gitattributes
Portfolio GitHub Pages'da Linux serverda ishlaydi, sizda esa Windows. Bir martalik tartibni qilamiz.
kurs/portfoliodagit status— ishchi papka toza bo'lsin.git ls-files --eol— qaysi fayllarw/crlf?i/crlfbormi?- Loyiha ildizida
.gitattributesyarating: asosiy qator,.batistisnosi, rasmlar uchunbinary(.png,.jpg,.webp,.ico) vapackage-lock.json -diff. git add --renormalize ., keyingit status -s. Qaysi fayllar chiqdi?.gitattributesni qo'shing vaGit: qator oxirlarini .gitattributes bilan tartiblaxabari bilan commit qiling.- Ishchi papkani yangilang (
git statustoza bo'lsa!) vagit ls-files --eolbilan tekshiring.
mashqlar repo: shu darsning 1–3-mashq javoblarini mashqlar/07/13-gitattributes/javoblar.md ga yozing va commit qiling: 07/13: .gitattributes mashqlari javoblarini qo'sh.
Yechim
.gitattributes:
* text=auto eol=lf
*.bat text eol=crlf
*.png binary
*.jpg binary
*.webp binary
*.ico binary
package-lock.json -diffBuyruqlar:
cd ~/kurs/portfolio
git status
git ls-files --eol
git add --renormalize .
git status -s
git add .gitattributes
git commit -m "Git: qator oxirlarini .gitattributes bilan tartibla"
git status
git rm -r --cached -q .
git reset --hard
git ls-files --eolBiz Birinchi repo darsidagi qisqa portfolio'da sinadik. Boshida fayllar i/lf w/crlf edi, --renormalize dan keyin git status -s faqat ?? .gitattributes ni ko'rsatdi. Commit:
[main 086fe19] Git: qator oxirlarini .gitattributes bilan tartibla
1 file changed, 7 insertions(+)
create mode 100644 .gitattributesOxirgi git ls-files --eol dan parcha:
i/lf w/lf attr/text=auto eol=lf .gitattributes
i/lf w/lf attr/text=auto eol=lf .gitignore
i/lf w/lf attr/text=auto eol=lf package-lock.json
i/lf w/lf attr/text=auto eol=lf sayt/index.html
...Agar sizda 4-qadamda M belgili fayllar chiqsa — ular CRLF bilan commit qilingan ekan, ular ham shu commitga tushadi. Bu normal. landing reposi git'ga o'tganda, unga ham xuddi shu faylni qo'shasiz.
11. Real ishda
- Deyarli har bir jiddiy ochiq loyihada
.gitattributesbor. Yangi loyiha ochganingizda.gitignorebilan birga birinchi yaratiladigan fayllardan biri. Hozir qo'shilsa — hech kim qator oxirlari haqida o'ylamaydi. - Docker va serverlar. Windows'da yozilgan CRLF'li
.shskript Linux serverda$'\r': command not foundbilan yiqiladi.eol=lfbu xatoni butunlay yo'q qiladi. Docker'ni keyingi qismlarda o'rganasiz — o'shanda bu qator sizni qutqaradi. - Katta binar fayllar (videolar, dizayn fayllari) uchun
.gitattributesda Git LFS qoidalari yoziladi. Git LFS — katta fayllarni repodan tashqarida saqlash usuli; uni Katta repolar darsida ko'rasiz. - Intervyuda "Windows va Mac'dagi dasturchilar bir loyihada ishlasa, qanday muammo chiqadi va uni qanday hal qilasiz?" — bu dars aynan shu savolga javob.
Xulosa
- Windows — CRLF, Linux va macOS — LF; farq ko'rinmas, lekin diff'ni buzadi.
core.autocrlf— shaxsiy sozlama, repo bilan yurmaydi; ogohlantirish shundan chiqadi..gitattributesda* text=auto eol=lf— butun jamoa uchun bitta qoida,core.autocrlfdan ustun.- Mavjud repoda:
.gitattributes→git add --renormalize .→ alohida commit; tekshiruv —git ls-files --eol. - Rasmlarga
binary, keraksiz diff'larga-diff, GitHub uchunlinguist-generated. .editorconfigmuharrirni,.gitattributesGit'ni boshqaradi — ikkalasi ham LF.
Keyingi dars: Kod arxeologiyasi: blame, log -S, log -L — "bu qator nega shunday yozilgan?" degan savolga tarixdan javob topamiz.
Manbalar
- Git hujjati: "gitattributes" (
text,eol,binary,diff, normalizatsiya tartibi), "git-add" (--renormalize), "git-ls-files" (--eol), "git-config" (core.autocrlf) — git-scm.com/docs - GitHub Docs: "Customizing how changed files appear on GitHub" (
linguist-generated) — docs.github.com
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!