Олег Марков
Игнорирование файлов в Git - как правильно использовать .gitignore
Введение
Файл .gitignore — один из тех инструментов Git, о котором часто вспоминают только тогда, когда в репозиторий случайно попадает что-то лишнее: огромный лог, секретный ключ, артефакты сборки или временные файлы IDE.
Смотрите, я покажу вам, как с помощью одного небольшого текстового файла можно:
- исключать из коммитов сгенерированные файлы и каталоги сборки;
- не допускать попадания в репозиторий конфиденциальных данных;
- поддерживать репозиторий в чистоте, чтобы в истории были только действительно важные изменения.
В этой статье вы разберетесь, как работает .gitignore, в каком порядке применяются правила, как писать шаблоны путей, чем он отличается от глобального игнора и .git/info/exclude, а также какие есть типичные ошибки и как их избегать.
Что такое .gitignore и как он работает
Общая идея .gitignore
Файл .gitignore — это текстовый файл, в котором вы перечисляете шаблоны файлов и папок, которые Git не должен отслеживать.
Ключевой момент: .gitignore влияет только на неотслеживаемые файлы. Если файл уже был добавлен в репозиторий и закоммичен, просто добавить его в .gitignore недостаточно — Git продолжит его видеть.
Git при каждом статусе/коммите:
- Сканирует рабочую директорию.
- Сопоставляет найденные неотслеживаемые файлы с шаблонами из .gitignore.
- Скрывает из статуса те, которые подходят под шаблоны.
Где хранится .gitignore
Файл .gitignore может находиться в нескольких местах:
- в корне репозитория — проектный .gitignore;
- в подкаталогах — локальные .gitignore для отдельных директорий;
- глобальный .gitignore для вашего пользователя в системе;
- файл .git/info/exclude — локальный игнор только для конкретного клона репозитория.
Давайте разберем каждый вариант подробнее.
Типы .gitignore и их приоритет
Проектный .gitignore (в корне репозитория)
Это самый распространенный вариант: вы создаете файл .gitignore в корне проекта, коммитите его, и он становится частью репозитория. Все участники проекта используют одни и те же правила игнорирования.
Пример типичного .gitignore в корне:
# Игнорируем каталоги сборки
build/
dist/
# Игнорируем временные файлы редакторов
*.swp # Временные файлы Vim
*.tmp # Разные временные файлы
# Игнорируем логи
logs/
*.log
Комментарии начинаются с #. Пустые строки игнорируются.
Локальные .gitignore в подкаталогах
Вы можете создать .gitignore в любом подкаталоге. Тогда его правила будут применяться относительно этого каталога и ниже.
Например, структура:
project/
.gitignore
backend/
.gitignore
frontend/
.gitignore
- Корневой .gitignore описывает общие правила для всего проекта.
- В
backend/.gitignoreвы можете добавить специфичные для бэкенда файлы, например миграции какого-то формата или артефакты сборки. - В
frontend/.gitignore— игнорироватьnode_modules/, файлы бандла, карты исходников и т.д.
Git идет сверху вниз по директориям и применяет правила из всех найденных .gitignore, при этом правила более глубоко расположенного .gitignore имеют больший приоритет.
Глобальный .gitignore (для всего пользователя)
Глобальный игнор — это файл, который применяется ко всем репозиториям текущего пользователя. Обычно в нем хранятся правила, связанные с вашей средой разработки:
- временные файлы IDE;
- файлы ОС (например,
.DS_Storeв macOS); - общие конфигурации редакторов, которые вы не хотите случайно закоммитить.
Как настроить глобальный .gitignore:
Создайте файл, например в домашней директории:
touch ~/.gitignore_globalУкажите Git использовать его:
git config --global core.excludesfile ~/.gitignore_globalДобавьте в него, например:
# macOS системные файлы .DS_Store # IDE .idea/ .vscode/ # Файлы резервных копий *~
Обратите внимание: глобальный .gitignore не коммитится, он применяется только у вас локально.
.git/info/exclude — игнор только для текущего клона
Если вам нужно игнорировать какие-то файлы только в конкретном клоне репозитория, и вы не хотите (или не можете) менять проектный .gitignore, используйте файл:
.git/info/exclude
Это по сути такой же .gitignore, но:
- он не коммитится;
- не виден другим разработчикам;
- действует только в этом конкретном репозитории.
Пример использования: вы храните локальный конфигурационный файл local.env, который не должен быть общим для команды. Вы можете добавить его в .git/info/exclude, не меняя общий .gitignore.
Синтаксис и шаблоны в .gitignore
Теперь давайте разберемся, как именно писать правила в .gitignore. От правильных шаблонов зависит, будут ли файлы корректно игнорироваться.
Базовые правила
- Одна строка — одно правило.
- Пустые строки игнорируются.
- Комментарии начинаются с
#. - Пробел в начале строки считается частью шаблона (если только строка не начинается с
#).
Пример:
# Это комментарий
# Игнорируем все .log файлы
*.log
# Игнорируем папку tmp
tmp/
Шаблоны с символом * (звездочка)
* — это подстановка для любого количества любых символов, кроме разделителя пути /.
Примеры:
*.log # Игнорируем все файлы, оканчивающиеся на .log
temp* # Игнорируем все, что начинается с "temp" (temp, temp1, temp_file.txt)
*backup* # Игнорируем все, где в имени есть "backup"
Обратите внимание, что * не переходит через /. То есть:
*/*.log # Игнорируются только .log файлы, которые лежат ровно в одном подкаталоге
Шаблоны с ? (один символ)
? соответствует ровно одному любому символу, кроме /.
file?.txt # file1.txt, fileA.txt, но не file10.txt
Шаблоны с [] (набор символов)
Скобки [] позволяют указать набор допустимых символов или диапазон:
file[0-9].txt # file0.txt, file1.txt, ..., file9.txt
file[ab].txt # filea.txt, fileb.txt
Слэш / и относительность путей
Слэш / в .gitignore важен, потому что он определяет, как Git трактует шаблон.
- Если путь не начинается со слэша, правило применяется к любому уровню вложенности.
- Если путь начинается со слэша, он интерпретируется относительно каталога, где лежит этот .gitignore.
Примеры:
# Игнорирует любой каталог build на любом уровне
build/
# В корневом .gitignore
/build/ # Игнорирует только build в корне репозитория
# Игнорирует все README.txt на любом уровне
README.txt
# В корневом .gitignore:
/README.txt # Игнорирует только README.txt в корне
Давайте разберем пример структуры, чтобы это было понятнее:
project/
.gitignore # содержит: /config.json
config.json # будет проигнорирован
sub/
config.json # НЕ проигнорирован, правило относится только к корню
Если же правило без начального /:
config.json # Игнорирует все config.json в проекте
Игнорирование каталогов
Чтобы явно указать, что вы хотите игнорировать каталог, добавьте слэш в конце:
logs/ # Любая папка logs с любым содержимым
tmp/
dist/
Если вы напишете просто:
logs
Git будет воспринимать это как правило и для файлов, и для папок с таким именем. В большинстве случаев удобнее явно использовать слэш для каталогов — это делает правило понятнее.
Отмена игнорирования с помощью !
Иногда нужно «разигнорировать» конкретный файл или каталог внутри игнорируемого. Для этого используется восклицательный знак ! в начале строки.
Давайте разберемся на примере:
# Игнорируем все логи
*.log
# Но один конкретный файл логов нам нужен
!important.log
Как видите, этот код в .gitignore говорит Git:
- не показывать в статусе все *.log;
- но файл
important.logвсе же учитывать.
Более сложный пример — частично игнорируем каталог:
# Игнорируем весь каталог config
config/
# Но файл config/example.yml нужно оставить
!config/
!config/example.yml
Здесь важный момент: чтобы «добраться» до файла, вам нужно:
- Сначала разигнорировать каталог
config/; - Потом разигнорировать нужный файл.
Если вы оставите только:
config/
!config/example.yml
То Git все равно не увидит example.yml, потому что родительская папка уже проигнорирована.
Использование шаблонов ** (рекурсивные пути)
Двойная звездочка ** работает как «любой уровень вложенности каталогов». Эта возможность особенно удобна в сложных структурах.
Примеры:
# Игнорировать все .log во всех подпапках любого уровня
**/*.log
# Игнорировать все каталоги build на любом уровне
**/build/
# Игнорировать все .tmp файлы в подпапках src любого уровня
src/**/**/*.tmp
Чаще всего вы будете видеть простые варианты:
**/node_modules/
**/.DS_Store
Но имейте в виду, что многие случаи и без ** уже корректно работают, потому что обычный шаблон без / и так применяется на всех уровнях.
Порядок применения правил и приоритет
Git применяет правила .gitignore сверху вниз и учитывает:
- Последнее подходящее правило для файла — главное.
- Более конкретные правила могут переопределять общие.
- Локальные .gitignore «ближе» к файлу имеют больший приоритет, чем корневые.
Пример с переопределением
Давайте посмотрим, что происходит в следующем примере:
# Игнорируем все .log
*.log
# Но файл в корне нужен
!important.log
- Сначала Git видит правило
*.log— файлimportant.logподпадает под него. - Затем он встречает правило
!important.log— и отменяет игнорирование конкретно для этого файла.
Еще пример:
# Игнорировать все в каталоге logs
logs/
# Кроме errors.log в корне logs
!logs/errors.log
Если в logs/ есть вложенные подкаталоги, они останутся проигнорированными, но logs/errors.log будет виден.
Взаимодействие разных .gitignore
Представьте структуру:
project/
.gitignore # 1
api/
.gitignore # 2
logs/
api.log
logs/
app.log
Содержимое корневого .gitignore:
logs/
Содержимое api/.gitignore:
!logs/
Что произойдет:
- В корневом .gitignore правило
logs/говорит: игнорировать любые папки с именем logs. - В
api/.gitignoreесть правило!logs/, которое применяется только в каталогеapiи ниже. - В результате:
logs/app.log— проигнорирован (подпадает под корневое правило, локального переопределения нет).api/logs/api.log— не проигнорирован (локальное правило вapi/.gitignoreотменяет игнорирование дляapi/logs/).
Работа с уже отслеживаемыми файлами
Одно из самых частых недоразумений: вы добавили файл в репозиторий, закоммитили его, затем добавили его шаблон в .gitignore — но Git все равно продолжает видеть изменения в этом файле.
Здесь важно понимать: .gitignore не удаляет и не перестает отслеживать файлы, которые уже находятся в индексе Git. Он управляет только тем, какие новые файловые пути не должны попадать в индекс.
Как перестать отслеживать файл, который уже в репозитории
Если вы случайно закоммитили файл, а затем решили его игнорировать:
- Добавьте его в .gitignore.
- Удалите его из индекса, но не из файловой системы.
Команды:
# Удаляем файл из индекса, но оставляем на диске
git rm --cached path/to/file.ext
# Фиксируем изменения (удаление файла из репозитория)
git commit -m "Stop tracking file.ext and add to .gitignore"
Комментарий к коду:
git rm --cached path/to/file.ext
# Опция --cached говорит Git:
# "убери файл только из индекса (репозитория),
# но не удаляй его с диска".
Теперь файл будет:
- присутствовать только у вас локально;
- не будет отслеживаться Git;
- скрываться в статусе благодаря записи в .gitignore.
Массовое прекращение отслеживания по шаблону
Если вы решили добавить в .gitignore целую категорию файлов, которая уже есть в репозитории (например, *.log), и хотите убрать их все из истории отслеживаемых файлов, можно сделать так:
# Обновляем индекс с учетом .gitignore
git rm -r --cached .
# Повторно добавляем все файлы (но уже без проигнорированных)
git add .
git commit -m "Apply .gitignore rules to existing files"
Комментарии:
git rm -r --cached .
# Удаляем из индекса все файлы рекурсивно, но не с диска
git add .
# Добавляем обратно только те файлы, которые не игнорируются
# согласно текущему .gitignore
С этим подходом будьте аккуратны в командной работе — перед выполнением таких команд убедитесь, что понимаете, какие файлы будут затронуты.
Типичные шаблоны .gitignore для разных проектов
Теперь давайте посмотрим на практические примеры, чтобы вам было проще взять готовые решения и адаптировать под свои проекты.
Общие шаблоны для большинства проектов
Часто во многих проектах используются одинаковые правила:
# Логи
logs/
*.log
# Временные файлы ОС
.DS_Store # macOS
Thumbs.db # Windows
# Временные файлы редакторов
*.swp # Vim
*.swo
*~
Здесь я размещаю пример, чтобы вам было проще понять, что стоит сразу исключать в любых репозиториях.
Пример .gitignore для Node.js проекта
# Зависимости
node_modules/
# Сборка и бандлы
dist/
build/
# Кэш
.npm/
.yarn/cache/
.yarn/*
!.yarn/patches/
!.yarn/plugins/
!.yarn/releases/
!.yarn/sdks/
!.yarn/versions/
# Логи
logs/
*.log
# Env файлы
.env
.env.local
.env.*.local
# Инструменты
coverage/ # Результаты тестов
.vscode/
.idea/
Обратите внимание, как этот фрагмент кода решает задачу: он исключает все временное, сгенерированное и локально специфичное, оставляя в репозитории только исходный код и важные конфиги.
Пример .gitignore для Python проекта
# Байт-код Python
__pycache__/
*.py[cod]
*$py.class
# Виртуальные окружения
venv/
.env/
.venv/
# Логи и отладочная информация
*.log
# Результаты тестов
.cache/
.coverage
htmlcov/
# Сборка пакетов
build/
dist/
*.egg-info/
# IDE
.idea/
.vscode/
Пример .gitignore для проектов на Go
# Бинарники Go
*.exe
*.exe~
*.dll
*.so
*.dylib
# Собранные бинарники
bin/
build/
# Тестовые артефакты
*.test
coverage.out
# IDE
.idea/
.vscode/
Использование готовых шаблонов из GitHub
GitHub предоставляет большое количество готовых .gitignore для разных языков и фреймворков: Java, .NET, Laravel, Django, React и многие другие.
Вы можете посмотреть их здесь:
https://github.com/github/gitignore
Удобный подход:
- Найти подходящий шаблон (например,
Python.gitignore). - Скопировать его содержимое.
- Вставить в свой .gitignore и при необходимости адаптировать.
Проверка и отладка .gitignore
Иногда вы добавляете правило в .gitignore, но Git «как будто не замечает его». Давайте посмотрим, что можно сделать в таких ситуациях.
Проверить, почему файл игнорируется или нет
Git предоставляет команду:
git check-ignore -v path/to/file
Комментарии:
git check-ignore -v path/to/file
# Показывает:
# - применяется ли к файлу правило игнора
# - из какого файла .gitignore оно взято
# - номер строки с правилом
Пример:
git check-ignore -v logs/app.log
Вы можете увидеть что-то вроде:
.gitignore:3:logs/ logs/app.log
Это означает, что файл игнорируется из-за третьей строки в .gitignore.
Если файл не игнорируется, команда не выведет ничего и вернет ненулевой код возврата.
Проверить, какие файлы игнорируются в целом
Иногда полезно увидеть список файлов, которые Git не показывает вам в статусе:
git status --ignored
Эта команда покажет, какие файлы:
- неотслеживаемые;
- проигнорированные .gitignore.
Лучшие практики использования .gitignore
Разделяйте «локальные» и «проектные» правила
Давайте разберемся на примере:
В проектный .gitignore лучше добавлять:
- каталоги сборки (build, dist);
- зависимостные директории (node_modules, vendor, target);
- логи, временные фалы, кэш тестов;
- стандартные временные файлы IDE, если ими пользуется вся команда.
В глобальный .gitignore лучше добавить:
- файлы вашей ОС (.DS_Store, Thumbs.db);
- файлы конкретных редакторов, которыми пользуетесь лично;
- кэш или вспомогательные файлы, которые не должны «протекать» в проекты.
Так вы избежите засорения проектного .gitignore сугубо личными настройками.
Не храните в репозитории секреты и конфиденциальные данные
Секретные ключи, токены, пароли, приватные сертификаты — все это лучше не добавлять в репозиторий даже случайно. Для таких файлов:
- Сразу добавьте общие шаблоны в .gitignore:
.env*.key*.pem
- Используйте шаблоны конфигов вида:
config.example.yml(в репозитории)config.yml(в .gitignore, локальная копия с настоящими секретами)
Пример:
# Реальные конфиги локальной среды
config.yml
.env
secrets.json
А в репозитории храните только пример:
# config.example.yml
database:
host: localhost
user: user
password: change_me # Здесь вы показываете структуру, но без настоящих значений
Добавляйте .gitignore в репозиторий как можно раньше
Лучший момент, чтобы создать .gitignore — перед первым коммитом. Тогда вы:
- не затащите в репозиторий мусор;
- не будете тратить время на «очистку» истории.
Если вы создаете проект через GitHub или GitLab, там часто уже предлагается выбрать шаблон .gitignore для соответствующего языка.
Будьте аккуратны с слишком общими шаблонами
Например, запись:
*.json
может скрыть из репозитория все JSON-файлы, включая важные конфиги, которые вы на самом деле хотели хранить в Git. Лучше указывать контекст:
logs/*.json # Логи в формате JSON
tmp/**/*.json # Временные JSON только в tmp
То же касается:
*.log
*.tmp
*.bak
Здесь лучше понимать, в каких каталогах они появляются, и при необходимости уточнять путь.
Старайтесь оставлять комментарии в .gitignore
Это поможет и вам, и другим участникам команды через пару месяцев понять, зачем добавлено то или иное правило.
Пример:
# Сборка фронтенда (генерируется Webpack)
dist/
# Кэш тестов Jest
coverage/
Заключение
Файл .gitignore — это простой, но очень важный инструмент в ежедневной работе с Git. Он помогает держать репозиторий в порядке, исключая из истории временные, сгенерированные и локально специфичные файлы.
Чтобы использовать .gitignore эффективно, важно понимать:
- где он может находиться (локальный, глобальный, .git/info/exclude);
- как работает синтаксис шаблонов (звездочки, вопросительные знаки, слэши,
**); - как отменять игнорирование с помощью
!; - что .gitignore не влияет на уже отслеживаемые файлы и как их перестать отслеживать.
Давайте теперь рассмотрим частые технические вопросы, которые возникают у разработчиков по теме .gitignore и не были подробно разобраны выше.
Частозадаваемые технические вопросы по .gitignore
1. Как игнорировать все файлы в каталоге, кроме одного типа или конкретного файла?
Если вам нужно игнорировать все, кроме, например, .md файлов:
docs/*
!docs/*.md
Комментарии:
docs/* # Игнорируем все в каталоге docs
!docs/*.md # Но разрешаем Markdown файлы
Если нужно оставить один конкретный файл:
config/*
!config/
!config/main.yml
Сначала игнорируем все, затем разигнорируем каталог и конкретный файл.
2. Как временно прекратить действие .gitignore для проверки?
Если вы хотите временно увидеть все файлы, будто .gitignore не существует, можно использовать:
git ls-files --others -i --exclude-standard
Чтобы увидеть, что именно игнорируется.
А чтобы просто игнор на время «выключить» без правки файлов, типичного флага нет, но вы можете:
Временно переименовать .gitignore:
mv .gitignore .gitignore.bak- Выполнить нужные команды (
git status,git add). Вернуть файл:
mv .gitignore.bak .gitignore
3. Почему .gitignore не работает для подмодулей Git submodule?
Подмодуль — это отдельный репозиторий внутри другого репозитория. .gitignore родительского репозитория не управляет содержимым подмодуля. Чтобы игнорировать файлы внутри подмодуля, нужно:
- Зайти в каталог подмодуля.
- Создать или отредактировать его собственный .gitignore.
- Закоммитить изменения в репозиторий подмодуля.
4. Как игнорировать файлы только для merge-конфликтов (например, локальный конфиг)?
Если вам нужно, чтобы файл не участвовал в слияниях, но оставался отслеживаемым, .gitignore не подойдет. Здесь используется атрибут Git:
В
.gitattributes:config.local merge=oursНастраиваете стратегию
ours:git config merge.ours.driver true
Теперь при merge Git всегда будет оставлять вашу локальную версию config.local, не пытаясь сливать изменения.
5. Можно ли условно игнорировать файлы в зависимости от ветки?
Сам .gitignore не поддерживает условия по веткам. Но можно использовать разные подходы:
- хранить разные .gitignore в разных ветках;
- использовать локальный
.git/info/excludeдля специфики вашей текущей работы; - применять скрипты-хуки, которые подменяют .gitignore при переключении веток.
Прямой механики «если ветка такая, игнорируй это» в .gitignore нет, поэтому обычно выбирают один из обходных путей в зависимости от сценария.
Постройте личный план изучения Git до уровня Middle — бесплатно!
Git — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по Git
Лучшие курсы по теме

Основы Git
Антон Ларичев
TypeScript с нуля
Антон Ларичев