Атрибути файлів
.gitattributes — найцінніший файл у git, який майже ніхто не пише. Саме
через нього репозиторій розповідає git про власний вміст: які файли
бінарні, які треба склеювати замість конфліктувати, які ніколи не потрапляють
в архів, які закінчення рядків отримують усі.
Найважливіше: він комітиться. Правило, яке ви додали, розв’язує проблему для кожного, хто зробить клон, на кожній ОС, назавжди — на відміну від налаштування у вашому власному конфізі, яке лагодить проблему вам, а колегам лишає можливість відкрити її для себе важким шляхом.
⌘K → Атрибути файлів.

Що роблять правила
| Атрибут | Що лагодить |
|---|---|
text=auto eol=lf |
Закінчення рядків, які стрибають залежно від того, хто зробив чекаут файлу |
binary |
Спроби git показати діф або зробити тристороннє злиття PSD, DOCX чи скомпільованого ресурсу |
merge=union |
Changelog, до якого всі дописують і на якому всі конфліктують |
-merge |
Файли, де тристороннє злиття дає нісенітницю — lock-файли, згенерований код |
export-ignore |
Конфіги CI та фікстури, що поїхали всередині релізного тарболу |
diff=<driver> |
Нечитабельні діфи для форматів, які насправді читабельні, якщо дати конвертер |
filter=lfs |
Великі файли, що зберігаються через LFS |
linguist-vendored |
Сторонній код, зарахований вам у мовній статистиці |
binary — це скорочення для -diff -merge -text, тобто три відповіді на
«припини вгадувати щодо цього файлу» одним словом.
Редагування
Пресети підставляють шаблон і його атрибути; відредагуйте шаблон перед
додаванням — CHANGELOG.md це пропозиція, а не правило про ваш проєкт.
Правки хірургічні. Додавання правила для шаблону, який його вже має, переписує той рядок там, де він стоїть, а не дописує друге правило, що перемагає лише завдяки пізнішій позиції. Коментарі у файлі лишаються недоторканими, бо «чому» поруч із правилом зазвичай вартує більше за саме правило.
Кожне збереження — звичайна дія Gitcito: вона показує сповіщення, а Скасувати повертає файл рівно таким, яким він був.
Репозиторій може мати кілька файлів атрибутів. Один у корені, один у
будь-якому підкаталозі, і приватний .git/info/attributes, який ніколи не
комітиться і діє лише на вашій машині — правильне місце для правила, що
стосується вас, а не проєкту. Gitcito перелічує їх усі й каже, що є що.
Що застосовується до шляху?
Правила приходять із кількох файлів, перемагає конкретніше, і читати їх, щоб
вивести відповідь, — це гадання. Що застосовується до шляху? запускає
git check-attr і показує, до чого доходить сам git — єдину відповідь, яка
має значення.
Діф-драйвери: як зробити документ Word читабельним
.docx — це zip. .pdf — стиснутий граф об’єктів. Git показує їхні діфи як
те, чим вони є — як шум, — тож історія документа нечитабельна, хоч сам
документ читабельний.
Діф-драйвер лагодить це через textconv: команду, яка перетворює файл на
текст лише для порівняння. Файл у вашому робочому дереві не змінюється; git
просто порівнює сконвертований текст.
Дві половини, і потрібні обидві:
diff.<name>.textconvу конфізі git — команда-конвертер.*.docx diff=<name>у.gitattributes— до яких файлів вона застосовується.
Кнопки тут роблять і те, і те одразу. Для Word, Excel, JSON і .strings Gitcito
постачає конвертер сам — той самий розбір документів, яким користуються
його попередні перегляди, відкритий як невелика команда gitcito-textconv
всередині застосунку, — тож ці чотири працюють без жодних встановлень. Решті все
ще потрібен справжній інструмент у вашому PATH: Gitcito перевіряє і притлумлює
те, чого бракує, замість писати драйвер, що зламається на першому ж діфі.
| Драйвер | Потребує | Дає вам |
|---|---|---|
word |
нічого — постачається з Gitcito | Діфи прози для .docx |
excel |
нічого — постачається з Gitcito | Порядкові діфи (CSV на кожен аркуш) для .xlsx/.xls |
json |
нічого — постачається з Gitcito | Стабільні діфи JSON із відсортованими ключами |
strings |
нічого — постачається з Gitcito | Порядковий diff .strings у UTF-16, який git називає двійковим |
pdf |
pdftotext (poppler) |
Текстові діфи для .pdf |
exif |
exiftool |
Що змінилося в зображенні, коли пікселі непрозорі |
Той, що кусає iOS-проєкти
Localizable.strings майже всю історію Xcode лежить у UTF-16, а UTF-16 повний
байтів NUL — тож git оголошує файл двійковим і не показує нічого:
diff --git a/Localizable.strings b/Localizable.strings
Binary files a/Localizable.strings and b/Localizable.strings differ
Саме тут найважливіше бачити, який рядок хтось зрушив. Драйвер strings
декодує файл лише для порівняння — читаючи позначку порядку байтів, а не
припускаючи її, тож сучасний .strings у UTF-8 проходить неушкодженим, а не
перетворюється на кракозябри.
String Catalog (.xcstrings, Xcode 15 і новіші) — це JSON, і його закриває
драйвер json: він сортує ключі, тож переклад, доданий згори, перестає
переписувати в дифі весь файл.
Межі вбудованого конвертера, названі прямо: .doc (старий двійковий формат
Word) він не розуміє — лише .docx; PDF не покрито — Gitcito показує PDF у
переглядачі браузера й не має видобувача тексту, який можна було б ужити
повторно; і кожен діф документа платить коротку ціну запуску конвертера.
Налаштування git config diff.<name>.cachetextconv true змушує git кешувати
вивід для кожного блоба.
Половина з конвертером живе у вашому конфізі, а не в репозиторії — git не
запускатиме команди, які вам підсунув клон, і це властивість безпеки, яку
варто берегти. До того ж вбудовані драйвери вказують на ваш шлях
встановлення Gitcito, тож колега, що зробить клон, отримає правило diff=word
і, доки не під'єднає власний конвертер (Gitcito чи будь-який інший), старий
нечитабельний діф. Напишіть про це у своєму README.
Фільтри clean/smudge — спершу пробний прогін
Фільтр переписує вміст на вході в репозиторій і на виході з нього: clean
запускається під час додавання в індекс (робоче дерево → репозиторій),
smudge — на чекауті (репозиторій → робоче дерево). Так працює git-lfs, і так
команди вирізають облікові дані чи згенерований шум із того, що потрапляє в
коміт.
Це водночас найнебезпечніше, на що може вказувати .gitattributes: фільтр
запускається на кожному чекауті кожного відповідного файлу, і хибний
фільтр тихо псує ваше робоче дерево. Тому Gitcito відмовляється бути тут
просто текстовим полем. Налаштування фільтра проходить через пробний
прогін на справжніх відповідних файлах вашого репозиторію:
- Команда
cleanзапускається на копії кожного відповідного файлу (до п’яти) — ніщо в репозиторії чи його конфізі не зачіпається. - Якщо задано команду
smudge, вона запускається на очищеному виводі, і результат порівнюється байт у байт з оригіналом — перевірка оборотності. Фільтр, який її не проходить, означає, що чекаут не поверне того, що у вас було. - Кнопка збереження вмикається лише після пробного прогону рівно на тих значеннях, які ви зберігаєте. Прогін, що не вдався — помилка команди, жоден файл не підійшов або розбіжна оборотність — усе ж можна зберегти, але лише через явне попередження, яке каже, що можна втратити.
Збереження записує filter.<name>.clean/smudge у ваш локальний конфіг git
і правило filter=<name> у файл атрибутів, а ще лишає запис скасування, який
повертає конфіг до того, що в ньому було раніше. Перемикач required
встановлює filter.<name>.required, через що git провалює операцію, замість
тихо пропускати файли, коли фільтр зламався.
Межі, названі прямо: пробний прогін бере до п’яти відповідних файлів не більше
5 МБ кожен, із таймаутом 10 секунд на команду — фільтр, що поводиться добре на
вибірці, все одно може повестися погано на файлі, якого вибірка не побачила.
Команди живуть у вашому конфізі, тож колега, що зробить клон, отримає
правило filter=<name>, але не команди; без них (і без required) його файли
проходять наскрізь без змін.
Обмеження, про які варто знати
text=autoзмінює те, що комітиться, нормалізуючи закінчення рядків на вході. У наявному репозиторії додайте його, а потім свідомо виконайтеgit add --renormalize .окремим комітом.- Атрибути не діють заднім числом. Позначивши файл як
binaryсьогодні, ви не змінюєте того, як зберігалися його минулі діфи; ви змінюєте те, як git ставиться до нього віднині. - Правила діють лише там, де файл видно. Правило в
design/.gitattributesне каже нічого проsrc/. - Gitcito пише файли цілком, тож файл, відформатований руками, повертається зі
своїм форматуванням — але правило, яке Gitcito переписав, форматується до
канонічних для git пробілів
pattern attr attr.
Дивіться також: LFS і розріджений чекаут · Бандли та архіви · Опції злиття · Хуки