.gitattributes

.gitattributes — это специальный текстовый файл в репозитории Git, в котором задаются правила (атрибуты) для разных групп файлов по маскам (шаблонам). Он позволяет гибко настраивать обработку файлов для нужд проекта, чтобы избежать проблем при совместной работе, архивации, слияниях, работе на разных ОС и т.д.

С помощью этого файла можно управлять тем, как Git обрабатывает файлы:

  • нормализует переводы строк (EOL).
  • определяет, что считать бинарным файлом.
  • настраивает обработку diff и merge.
  • применяет фильтры и спец. правила для архивации.
  • управляет кодировкой и автоподстановкой значений.

Каждая строка в файле — это правило вида:

шаблон атрибут1 атрибут2 ...

Например:

# для всех PNG-файлов задать поведение как для бинарных
*.png binary

Расположение файла

Файл может располагаться в корне репозитория, в подпапках или в служебных местах.

Порядок приоритетности — позднее найденное правило перебивает более раннее по каждому атрибуту:

  1. .git/info/attributes (локальный) — текущий репозиторий, перебивает всё (наивысший приоритет).
  2. .gitattributes (локальный) — ближайший к файлу, перебивает глобальный и системный.
  3. core.attributesFile (глобальный) — для всех ваших репозиториев.
  4. $(prefix)/etc/gitattributes (системный) — для всех пользователей в системе (самый низкий приоритет).

Пример:

  • Атрибут из .git/info/attributes перебьёт все остальные.
  • Атрибут из .gitattributes (ближайший к файлу) перебьёт глобальный и системный.
  • Если нет локальных правил, Git смотрит глобальный конфиг, потом системный.

Синтаксис строки

шаблон атрибут1 атрибут2 ...
  • Например: *.jpg binary

  • Комментарии: строка с #

  • Пробелы игнорируются

  • Шаблоны — как в .gitignore, но:

    • Отрицательные (!) — нельзя.
    • folder/ не рекурсивен — нужно использовать folder/**.
    • Поздние строки перебивают ранние (по каждому атрибуту отдельно).

Состояния атрибута

Это способ указать для Git, как применять конкретный атрибут к файлу или группе файлов.

Каждое состояние определяет, включён или отключён атрибут, или задано для него конкретное значение:

  • attr — Атрибут включён (Git считает его установленным, значение "true").
    Пример: *.txt text

  • -attr — Атрибут отключён (Git считает его сброшенным, значение "false").
    Пример: *.bin -text

  • attr=value — Атрибуту присваивается конкретное строковое значение.
    Пример: *.sh eol=lf

  • !attr — Атрибут сбрасывается в неопределённое состояние (Unspecified), как будто правило для него не задано вообще.
    Пример: *.log !text

Атрибуты

binary
Встроенный макро-атрибут: эквивалентен -diff -merge -text.
Нужно указывать для бинарных файлов. Например: *.png binary.
text

Указывает Git считать файл текстовым и применять нормализацию переводов строк (LF в репозитории, EOL в рабочей копии).

  • text — всегда считать текстом (LF в индексе, автоконвертация при checkout по OS)
  • -text — не трогать переводы строк, считать бинарником
  • text=auto — Git сам определяет (рекомендуется для кроссплатформы)
eol

Явно задаёт тип перевода строк в рабочей копии (в файлах проекта на вашем компьютере):

  • eol=lf — только LF
  • eol=crlf — только CRLF

Работает только если включён text или text=auto:

*.sh  text eol=lf
diff

Управляет тем, как Git строит различия (diff) для файла:

  • diff — форсировать обычный текстовый diff.
  • -diff — не показывать diff (Binary files differ).
  • diff=driver — использовать указанный diff-драйвер. Например, diff=php.

В Git есть несколько встроенных diff-драйверов по языкам/форматам: ada, bash, bibtex, cpp, csharp, css, dts, elixir, fortran, fountain, golang, html, java, kotlin, markdown, matlab, objc, pascal, perl, php, python, ruby, rust, scheme, tex.

merge

Управляет тем, как Git сливает (merge) изменения файла.

  • merge — использовать стандартный текстовый merge (3-way merge с конфликтами)
  • -merge — всегда считать конфликтным, оставить только вашу версию
  • merge=driver — использовать указанный merge-драйвер. Например, merge=binary или кастомный драйвер.
filter

Указывает Git применять внешний фильтр к файлу при добавлении (clean) или извлечении (smudge) из репозитория.

Фильтры используются, например, для автоматического преобразования файлов при сохранении или восстановлении (например, сжатие, шифрование, форматирование и др.).

filter=name — имя фильтра, который настроен в конфиге .git/config.

Например:

[filter "myfilter"]
	clean = команда-для-clean
	smudge = команда-для-smudge
*.ext  filter=myfilter
export-ignore

Говорит Git не включать указанные файлы/папки в архивы, создаваемые командой git archive (например, zip или tar).

Например: tests/ export-ignore.

Архивация используется для релизов и при создании архивово в GitHub / GitLab.

Если пакет собирается через Packagist, он тоже использует git archive, а значит учитывает export-ignore. Все файлы с этим атрибутом не попадут в дистрибутив Composer-пакета.

Файлы с export-ignore сохраняются при клонировании.

export-subst

Включает автоматическую подстановку плейсхолдеров (например, информации о коммите) в файле при создании архива через git archive.

Для автозамены шаблонов, как $Format:%H$ (хеш коммита), в контенте файла.

Пример:

VERSION export-subst

Теперь указываем шаблон в файле VERSION:

Commit: $Format:%H$
Date: $Format:%cI$

При создании архива через git archive эти плейсхолдеры заменятся на актуальные значения.

При клонировании шаблон останется как есть.

Списко плейсхолдеров:

$Format:%H$      — полный хеш коммита
$Format:%h$      — короткий хеш
$Format:%an$     — автор (имя)
$Format:%ae$     — автор (email)
$Format:%ad$     — дата коммита (локальная)
$Format:%cd$     — дата коммита (локальная, коммиттер)
$Format:%cI$     — дата в формате ISO
$Format:%s$      — сообщение коммита
$Format:%d$      — рефы (теги, ветки)
$Format:%D$      — рефы (полные)
$Format:%(describe)$ — git describe (тег/коммит)

Полный список: https://git-scm.com/docs/git-log

working-tree-encoding

Указывает Git, в какой кодировке файл должен быть в рабочей копии.

В репозитории файл хранится в UTF-8, а при checkout/commit автоматически конвертируется из/в нужную кодировку.
Пример:

*.ps1 text working-tree-encoding=UTF-16LE eol=crlf

Полезно для файлов, которые по требованиям должны быть не в UTF-8 (например, скрипты для Windows).

  • Работает только при установленном text или text=auto.
  • Не все версии Git и сторонние клиенты поддерживают этот атрибут.
  • Для проверки доступных кодировок используй: iconv --list
ident

Позволяет автоматически подставлять в файл хеш коммита вместо строки $Id$ при извлечении из репозитория (checkout).

Используется для идентификации версии файла. Чтобы прямо в файле видеть, из какого коммита он был получен.

Например в файле пишем:

Версия: $Id$

Если для файла включён ident, после checkout получится:

Версия: $Id: <хеш файла> $
whitespace

Управляет проверкой ошибок пробелов и табов при работе с diff и patch.

Используется для более строгого контроля стиля кода на уровне репозитория.

  • whitespace — включить все стандартные проверки (лишние пробелы, табы, пробелы в конце строк и др.)
  • -whitespace — отключить все проверки
  • whitespace=option1,option2 — включить только указанные проверки (например, whitespace=trailing-space,tab-in-indent)

Пример:

*.py  whitespace=tab-in-indent,trailing-space
conflict-marker-size

Задаёт длину конфликтных маркеров (<<<<<, =====, >>>>>) при возникновении конфликтов слияния (merge).

По умолчанию маркеры длиной 7 символов. Можно увеличить, чтобы маркеры было лучше видно.

Пример:

*.md  conflict-marker-size=32

Теперь маркеры в конфликте для .md файлов будут длиной 32 символа.

Макро-атрибуты

Это сокращение, которое задаёт сразу несколько атрибутов для файлов.

Например, стандартный макро-атрибут binary эквивалентен -text -diff -merge.

Можно создать свой макро-атрибут, чтобы не повторять одни и те же атрибуты для разных файлов.

Кастомные макро-атрибуты можно задавать только в корневом файле .gitattributes или в .git/info/attributes.

Пример создания макро-атрибута mybin:

[attr]mybin  -text -diff -merge   # объявление макро-атрибута mybin

*.foo  mybin   # применить (-text -diff -merge) ко всем *.foo файлов
*.bar  mybin   # применить (-text -diff -merge) ко всем *.bar файлов

По умолчанию в Git есть только один встроенный макро-атрибут:

  • binary — устанавливает сразу три атрибута: -diff -merge -text

Примеры

Исключения файлов из архива

Этот конфиг исключит указанные файлы из Composer-пакета (Packagist). Все файлы с этим атрибутом не попадут в дистрибутив.

/tests/     export-ignore
*.md        export-ignore
secret.txt  export-ignore

Демо

Эти правила охватывают обработку переводов строк, бинарных файлов, работу с архивами и распространённые исключения:

# Для всех текстовых файлов — автоопределение
* text=auto

# Принудительный LF для скриптов
*.sh text eol=lf

# CRLF для файлов Visual Studio
*.vcproj text eol=crlf

# Для картинок — бинарные, diff/merge отключён
*.jpg  binary
*.png  binary
*.gif  binary

# Не включать тесты в архивы
/tests/ export-ignore

# Подстановка информации о коммите в файл VERSION при архивировании
VERSION export-subst

# Принудительно отключить нормализацию строк для PDF
*.pdf -text

Массовая нормализация EOL

echo "* text=auto" > .gitattributes
git add --renormalize .
git status  # покажет файлы, где изменилась нормализация
git commit -m "Normalize line endings"

Исключения можно задать явным -text для файлов/паттернов.