Гайд по .gitignore: что игнорировать и как работают шаблоны
Практика3 минРедакция Innovialabs
Коротко
.gitignore говорит Git, какие неотслеживаемые файлы не добавлять в репозиторий: зависимости, сборки, локальные настройки и секреты; на уже закоммиченные файлы он не действует — их нужно убрать через git rm --cached.
Что делает .gitignore
.gitignore — текстовый файл со списком шаблонов. Файлы, которые им соответствуют, Git не показывает в git status и не добавляет через git add ..
Главное, что нужно помнить: .gitignore работает только для неотслеживаемых файлов. Если файл уже был закоммичен, добавление его в .gitignore ничего не изменит — Git продолжит следить за ним.
Что обычно игнорируют:
- зависимости:
node_modules/,.venv/,Pods/; - результаты сборки:
dist/,build/, кеши; - локальные настройки: файлы IDE,
.DS_Store,Thumbs.db; - секреты:
.env, ключи, сертификаты, keystore.
Что не игнорируют: исходный код, lock-файлы (package-lock.json, poetry.lock) и примеры конфигов вроде .env.example.
Синтаксис шаблонов
| Шаблон | Что совпадает |
|---|---|
debug.log | Файл или папка с таким именем на любом уровне |
*.log | Все файлы с расширением .log |
build/ | Только папки build (слеш в конце) |
/config.local.json | Только в корне, рядом с этим .gitignore |
docs/*.pdf | PDF прямо в docs, но не во вложенных папках |
**/temp | temp на любой глубине |
logs/** | Всё содержимое папки logs |
a/**/b | a/b, a/x/b, a/x/y/b |
file?.txt | Ровно один любой символ |
[abc].txt | Один символ из набора |
Правила, которые чаще всего путают:
*не проходит через/. Чтобы захватить вложенные папки, нужен**.- Если в шаблоне есть слеш в начале или в середине, он привязан к папке, где лежит .gitignore. Без слеша — совпадает на любом уровне.
- Строки с
#— комментарии. Пустые строки игнорируются.
Отрицание и вложенные файлы
Восклицательный знак ! возвращает файл, который исключил предыдущий шаблон:
*.env
!example.env
Ловушка: нельзя вернуть файл, если исключена вся его папка. Git просто не заходит внутрь. Так не сработает:
logs/
!logs/.gitkeep
А так сработает — исключаем содержимое, а не саму папку:
logs/*
!logs/.gitkeep
Вложенные .gitignore. В любой подпапке можно положить свой .gitignore. Его шаблоны считаются относительно этой папки, а при конфликте выигрывает более глубокий файл.
.git/info/exclude — те же правила, но файл не коммитится. Подходит для личных исключений в одном репозитории.
Глобальный gitignore
Мусор от вашей ОС и редактора лучше игнорировать один раз для всех проектов, а не в каждом репозитории:
git config --global core.excludesFile ~/.gitignore_global
Туда хорошо подходят .DS_Store, Thumbs.db, .idea/, .vscode/, *.swp. В проектный .gitignore кладите то, что касается самого проекта и всех его участников.
Готовые шаблоны
Node.js / фронтенд:
node_modules/
dist/
build/
.next/
coverage/
npm-debug.log*
.env
.env.*
!.env.example
Python:
__pycache__/
*.py[cod]
.venv/
venv/
*.egg-info/
dist/
build/
.pytest_cache/
.mypy_cache/
.env
Мобильные (Android, iOS, Flutter):
# Android
.gradle/
build/
local.properties
*.jks
*.keystore
# iOS
xcuserdata/
DerivedData/
*.xcuserstate
# Flutter
.dart_tool/
Коммитить ли Pods/ в iOS — решение команды; оба варианта встречаются. Большая коллекция шаблонов поддерживается на GitHub в репозитории github/gitignore.
Как убрать файлы, которые уже в репозитории
Если файл уже отслеживается, добавьте его в .gitignore и уберите из индекса, не удаляя с диска:
git rm --cached config.local.json
git rm -r --cached build/
git commit -m "Stop tracking local files"
Проверить, какое правило срабатывает: git check-ignore -v путь/к/файлу.
С секретами так нельзя. git rm --cached убирает файл только из следующих коммитов, а в истории он остаётся, и любой с доступом к репозиторию его найдёт. Порядок действий:
- Сразу отзовите и замените ключ, пароль или токен. Считайте его скомпрометированным.
- Уберите файл из отслеживания и добавьте в .gitignore.
- При необходимости перепишите историю (
git filter-repoили BFG Repo-Cleaner), сделайте force push и попросите команду заново склонировать репозиторий.
Переписывание истории без замены секрета не помогает: копии репозитория могли уже разойтись.
Подробно синтаксис описан в официальной документации Git.