.gitattributes — fayl turlari, line ending, diff sozlash

~10 daq · Git · Amaliy va Professional mavzular

Muammodan boshlaylik

Jamoada Windows, macOS va Linux foydalanuvchilari. Kunlardan bir kun:

  • Malika (Windows) faylda bitta qatorni o'zgartirdi — git diff butun fayl o'zgarganini ko'rsatadi
  • Serverda deploy skripti xato beradi: /bin/bash^M: bad interpreter
  • package-lock.json dagi har bir conflict — 3000 qatorli dahshat
  • PR da logo.png uchun ma'nosiz "Binary files differ"

Sababi — Git fayllarni qanday qayta ishlashi sozlanmagan. 3-darsdagi core.autocrlf — har bir dasturchining shaxsiy sozlamasi; kimdir uni unutadi. Kerak — loyiha darajasidagi, repozitoriyda saqlanadigan qoidalar. Bu — .gitattributes.


.gitattributes nima?

Loyiha ildizidagi fayl (.gitignore kabi): har bir qator — naqsh va atributlar:

naqsh    atribut1 atribut2=qiymat
*.sh     text eol=lf
*.png    binary

Repozitoriyga commit qilinadi — jamoadagi hamma, CI va serverlar uchun bir xil qoidalar.


1. Qator oxirlari — eng muhim qism

Windows — CRLF (\r\n), Linux/macOS — LF (\n) (3-dars). Aralash bo'lsa — soxta diff lar va buzilgan skriptlar.

Universal boshlang'ich .gitattributes:

# Barcha matnli fayllarni Git o'zi aniqlasin va repozitoriyda LF da saqlasin
* text=auto

# Har doim LF bo'lishi shart bo'lganlar (Linux da ishlaydi)
*.sh          text eol=lf
Dockerfile    text eol=lf
*.yml         text eol=lf

# Windows uchun — CRLF
*.bat         text eol=crlf
*.cmd         text eol=crlf
*.ps1         text eol=crlf

# Binar fayllar — hech qanday o'zgartirish yo'q
*.png         binary
*.jpg         binary
*.gif         binary
*.ico         binary
*.pdf         binary
*.woff2       binary
*.zip         binary
Atribut Ma'nosi
text=auto Git matn yoki binar ekanini o'zi aniqlaydi; matnlar repozitoriyda LF
text eol=lf Ishchi papkada ham doim LF (OS dan qat'i nazar)
text eol=crlf Ishchi papkada doim CRLF
binary Matn emas: qator oxiri o'zgartirilmaydi, diff ko'rsatilmaydi, merge qilinmaydi
-text Matn sifatida qayta ishlanmasin

.gitattributes core.autocrlf dan ustun — shaxsiy sozlamalar muhim emas bo'lib qoladi.

Mavjud repozitoriyni normallashtirish

.gitattributes ni qo'shgandan keyin, allaqachon CRLF bilan saqlangan fayllarni tuzatish:

git add --renormalize .
git status                      # qaysi fayllar o'zgardi
git commit -m "chore: qator oxirlarini normallashtirish"

Bu bitta katta commit bo'ladi — uni alohida qiling va jamoaga oldindan xabar bering.


2. Diff ni sozlash

Generatsiya qilingan fayllar

package-lock.json, pnpm-lock.yaml, *.min.js, dist/ — odam o'qimaydi:

package-lock.json   -diff linguist-generated
pnpm-lock.yaml      -diff linguist-generated
*.min.js            -diff
  • -diff — git diff da "Binary files differ" o'rniga qisqa xabar; terminal minglab qatorga to'lmaydi
  • linguist-generated — GitHub PR da bu fayllar avtomatik yig'iladi ("Load diff" tugmasi ortida) — reviewerlar haqiqiy kodga e'tibor qaratadi

Tilga xos diff

*.php     diff=php
*.py      diff=python
*.md      diff=markdown
*.css     diff=css

@@ sarlavhasida o'zgarish qaysi funksiya ichida ekanini ko'rsatadi (10-dars):

@@ -42,7 +42,7 @@ function narxHisobla($mahsulot)

3. Merge strategiyalari

CHANGELOG.md     merge=union

union — conflict o'rniga ikkala tomonning qatorlarini qoldiradi. Ikki branch CHANGELOG ga turli qatorlar qo'shganda qulay (natijani ko'zdan kechiring).

Lock fayllar uchun conflict da — 16-darsdagi usul: bir tomonni olib, qayta yaratish.


4. Arxivdan chiqarish

48-darsdan:

/tests          export-ignore
/.github        export-ignore
.gitattributes  export-ignore

git archive, GitHub "Download ZIP", reliz arxivlari — bu fayllarsiz.


5. GitHub Linguist — til statistikasi

Repozitoriy sahifasidagi rangli chiziq ("JavaScript 78%, CSS 15%...") — Linguist. Uni tuzatish:

docs/**         linguist-documentation
vendor/**       linguist-vendored
*.blade.php     linguist-language=PHP
public/build/** linguist-generated

Vendor va generatsiya qilingan kod statistikadan chiqariladi — loyiha tili to'g'ri ko'rinadi.


6. Git LFS

Katta binar fayllar uchun atribut (keyingi dars):

*.psd    filter=lfs diff=lfs merge=lfs -text
*.mp4    filter=lfs diff=lfs merge=lfs -text

Bu qatorlarni git lfs track o'zi qo'shadi.


Tekshirish

git check-attr -a src/deploy.sh
src/deploy.sh: text: set
src/deploy.sh: eol: lf
git ls-files --eol | head
i/lf    w/lf    attr/text eol=lf      deploy.sh
i/lf    w/crlf  attr/text=auto        src/app.js
i/-text w/-text attr/-text            logo.png

i/ — repozitoriyda (index), w/ — ishchi papkada. i/crlf ko'rsangiz — repozitoriyda CRLF saqlangan, normallashtirish kerak.

Tayyor shablonlar: github.com/gitattributes/gitattributes — Common.gitattributes, Web.gitattributes va boshqalar.


Nima uchun shunday?

Nima uchun bunday sozlamalar shaxsiy git config da emas, repozitoriydagi faylda bo'lishi kerak?

Chunki ular fayllarning xususiyati, dasturchining afzalligi emas. deploy.sh Linux serverda ishlashi uchun LF bo'lishi kerak — bu skriptning o'ziga tegishli haqiqat, uni kim va qaysi OS da clone qilganidan qat'i nazar. Shaxsiy sozlama bilan bu haqiqat har bir dasturchining to'g'ri sozlashiga bog'liq — va yangi xodim, CI runner yoki unutuvchan hamkasb buni buzadi. Repozitoriydagi .gitattributes esa qoidani kod bilan birga olib yuradi: clone qilgan har kim avtomatik to'g'ri xatti-harakatni oladi. Bu .gitignore, .editorconfig va Prettier sozlamalari bilan bir xil falsafa: loyiha qoidalari — loyiha ichida.


Xulosa

Eslab qoling:

  • .gitattributes — loyiha darajasidagi fayl qoidalari, repozitoriyda
  • * text=auto — boshlang'ich; *.sh text eol=lf; *.bat text eol=crlf
  • *.png binary — o'zgartirish, diff va merge yo'q
  • Mavjud repo: git add --renormalize .
  • -diff linguist-generated — lock fayllar diff da va PR da yig'iladi
  • diff=php va h.k. — funksiya nomlari diff sarlavhasida
  • merge=union, export-ignore, linguist-vendored
  • Tekshirish: git check-attr -a fayl, git ls-files --eol

Keyingi dars

53-dars: Git LFS — katta fayllar bilan ishlash