Файл .gitignore: как исключить файлы из Git и убрать уже добавленные
Файл .gitignore в корне репозитория перечисляет шаблоны файлов и папок, которые Git не будет отслеживать: зависимости, сборки, логи, секреты. Он действует только на неотслеживаемые файлы, поэтому уже закоммиченный файл нужно убрать из индекса командой git rm --cached.
Механизм git ignore — это способ сказать Git: «эти файлы не трогай, не показывай в git status и не добавляй через git add .». Правила пишутся в текстовом файле .gitignore, который коммитится вместе с проектом и работает для всей команды. Главная тонкость: игнор действует только на файлы, которые Git ещё не отслеживает.
Что обычно добавляют в .gitignore
- Зависимости:
node_modules/,vendor/,.venv/— их восстанавливает менеджер пакетов. - Результаты сборки:
dist/,build/,*.class,__pycache__/. - Логи и временные файлы:
*.log,tmp/,*.swp. - Секреты и локальные настройки:
.env, ключи, локальные конфиги. - Мусор ОС и редакторов:
.DS_Store,Thumbs.db,.idea/— хотя их лучше держать в глобальном игноре, о нём ниже.
Правило простое: в репозитории должно быть то, что пишут люди, а не то, что генерируют программы или что зависит от конкретной машины.
Как создать .gitignore
Это обычный текстовый файл в корне репозитория. Создайте его, впишите шаблоны по одному на строку и закоммитьте:
cat > .gitignore <<'EOF'
# зависимости
node_modules/
# сборка
dist/
# логи
*.log
# секреты
.env
EOF
git add .gitignore
git commit -m "chore: добавлен .gitignore"
Готовые шаблоны для популярных языков и фреймворков есть в репозитории github/gitignore; GitHub и GitLab предлагают выбрать шаблон при создании проекта. Берите их за основу и убирайте лишнее.
Синтаксис шаблонов .gitignore
| Шаблон | Что игнорирует |
|---|---|
*.log | все файлы с расширением .log в любой папке |
build/ | папку build на любом уровне (слэш в конце = только папки) |
/build | только build в корне (слэш в начале привязывает к папке .gitignore) |
docs/*.pdf | pdf прямо в docs, но не в docs/old/ |
docs/**/*.pdf | pdf в docs и всех вложенных папках |
**/temp | temp в любой папке |
!keep.log | исключение: не игнорировать keep.log |
file?.txt | ? — один любой символ |
[ab].txt | a.txt или b.txt |
# комментарий | строка-комментарий |
Важный нюанс: шаблон без слэша внутри (config.json) срабатывает на любом уровне, а шаблон со слэшем в начале или середине (/config.json, src/config.json) — относительно папки, где лежит этот .gitignore.
Исключения через восклицательный знак
*.log
!important.log
Ловушка: нельзя «вернуть» файл, если игнорируется его родительская папка. Git не заходит в игнорируемые папки, поэтому так не сработает:
logs/
!logs/keep.txt # не работает
Правильно — игнорировать содержимое, а не папку:
logs/*
!logs/keep.txt
Этим же приёмом сохраняют пустую папку в репозитории: Git не хранит пустые каталоги, поэтому в неё кладут файл .gitkeep и разрешают только его.
Где ещё можно задать игнор
| Место | Действует на | Попадает в репозиторий |
|---|---|---|
.gitignore в корне и подпапках | всю команду | да |
.git/info/exclude | только этот клон | нет |
глобальный файл core.excludesFile | все ваши репозитории | нет |
Мусор вашей ОС и IDE разумно убрать в глобальный игнор, чтобы не засорять общий .gitignore:
git config --global core.excludesFile ~/.gitignore_global
echo ".DS_Store" >> ~/.gitignore_global
echo ".idea/" >> ~/.gitignore_global
Если core.excludesFile не задан, Git читает ~/.config/git/ignore, если он существует.
Почему .gitignore не работает
Самая частая жалоба: «добавил файл в .gitignore, а Git всё равно показывает изменения». Причина почти всегда одна — файл уже отслеживается. Игнор не влияет на файлы, которые однажды попали в коммит.
Проверить, какое правило срабатывает (или почему не срабатывает), помогает git check-ignore:
git check-ignore -v logs/app.log
# .gitignore:3:*.log logs/app.log
Вывод показывает файл и строку правила. Пустой вывод означает, что файл не игнорируется. Ещё одна причина сбоев — пробелы в конце строки шаблона или неверная кодировка файла (например, UTF-16 при создании через PowerShell).
Как убрать из репозитория уже закоммиченный файл: git rm --cached
Команда git rm удаляет файл из индекса и с диска. С флагом --cached — только из индекса: файл остаётся у вас, но перестаёт отслеживаться.
echo ".env" >> .gitignore
git rm --cached .env
git commit -m "chore: .env больше не отслеживается"
git push
Для папки нужен -r:
git rm -r --cached node_modules/
Если правил много и неясно, что уже попало в репозиторий, можно пересобрать индекс целиком: git rm -r --cached ., затем git add . и коммит. Перед коммитом проверьте git status — там будут видны удалённые из индекса файлы.
Внимание: секреты остаются в истории
git rm --cached убирает файл из следующих коммитов, но не из прошлых. Если в репозиторий попал пароль или токен, он доступен в истории любому, у кого есть клон. Секрет нужно считать скомпрометированным и перевыпустить. Переписать историю можно инструментами вроде git filter-repo, но это меняет хеши всех последующих коммитов и требует согласования с командой.
Ещё одно следствие: у коллег после git pull файл, удалённый из индекса через --cached, будет удалён с диска. Для .env предупредите команду заранее или держите шаблон .env.example в репозитории.
git rm: удаление файлов
git rm old.py # удалить с диска и из индекса
git rm -r legacy/ # удалить папку
git rm -n '*.tmp' # dry run: показать, что будет удалено
git rm -f changed.py # удалить файл с незакоммиченными изменениями
Если удалить файл обычным rm, Git увидит его как «deleted», и удаление придётся добавить через git add или git rm. git rm делает оба шага сразу. Без -f он откажется удалять файл с незакоммиченными правками — это защита от потери работы.
git mv: переименование и перемещение
git mv utils.py helpers.py
git mv helpers.py src/helpers.py
git mv — сокращение для mv + git rm старого пути + git add нового. Git не хранит факт переименования: он вычисляет его по схожести содержимого при выводе git status, git log --follow и git diff. Поэтому переименование и обычный mv с последующим git add -A дают одинаковый результат.
Практический совет: переименовывайте и меняйте содержимое файла в разных коммитах. Если файл сильно изменился вместе с переименованием, Git может не распознать его как тот же файл, и история по --follow оборвётся.
Для смены только регистра имени на Windows и macOS (файловые системы нечувствительны к регистру) используйте git mv readme.md README.md — простое переименование в проводнике Git может не заметить.
Порядок правил и приоритет
Внутри одного файла правила читаются сверху вниз, и последнее подходящее побеждает. Поэтому исключение !keep.log должно стоять ниже правила *.log, иначе оно будет перекрыто. Между файлами приоритет такой: .gitignore во вложенной папке важнее корневого, а глобальный игнор и .git/info/exclude имеют самый низкий приоритет.
Пример .gitignore для веб-проекта
Ниже — рабочий вариант для проекта на Node.js с бэкендом на Python. Обратите внимание на комментарии: через полгода никто не вспомнит, зачем добавлено то или иное правило.
# --- зависимости ---
node_modules/
.venv/
# --- сборка и кэши ---
/dist
/build
__pycache__/
*.pyc
.pytest_cache/
coverage/
# --- логи ---
*.log
npm-debug.log*
# --- окружение и секреты ---
.env
.env.*
!.env.example
# --- загрузки пользователей, но папку сохраняем ---
uploads/*
!uploads/.gitkeep
Здесь использованы оба приёма с исключениями: .env.* скрывает все локальные варианты окружения, но шаблон .env.example остаётся в репозитории, а папка uploads существует в клоне благодаря .gitkeep.
Что не стоит игнорировать
Перегибать с игнором тоже вредно. Файлы блокировки зависимостей — package-lock.json, poetry.lock, composer.lock — в приложениях обычно коммитят: они гарантируют, что у всех разработчиков и в CI ставятся одинаковые версии пакетов. Общие настройки форматирования (.editorconfig, конфиги линтеров) тоже должны жить в репозитории.
Спорный случай — настройки IDE. Папку .vscode/ часто игнорируют целиком, но иногда коммитят рекомендуемые расширения и задачи сборки: .vscode/*, затем !.vscode/extensions.json. Решение принимает команда, главное — не держать в общем репозитории личные пути и ключи.
Сценарий: случайно закоммитили node_modules
Классическая ошибка новичка: git add . до создания .gitignore, и в коммит улетают десятки тысяч файлов. Исправление в три шага:
echo "node_modules/" >> .gitignore
git rm -r --cached node_modules
git commit -m "chore: node_modules убраны из репозитория"
Если коммит ещё не отправлен на сервер, аккуратнее переписать его, чтобы тяжёлые файлы не остались в истории: git reset --soft HEAD~1, затем те же команды и новый коммит. После push файлы уже в истории, и размер клона не уменьшится без переписывания истории.
Чтобы такое не повторялось, создавайте .gitignore до первого git add и привыкайте перед коммитом смотреть git status: подозрительно длинный список новых файлов — повод остановиться.
Итог
Файл .gitignore — первый файл, который стоит закоммитить в новом проекте: зависимости, сборки, логи и секреты в репозитории не нужны. Игнор работает только для неотслеживаемых файлов, поэтому уже добавленное убирают через git rm --cached, а проверяют правила через git check-ignore -v. Для удаления и переименования используйте git rm и git mv, чтобы изменения сразу попадали в индекс. Работа с индексом и первым репозиторием разобрана на практике в курсе по Git.
Частые вопросы
Нужно ли коммитить сам .gitignore?
Да, чтобы правила действовали у всей команды; личные исключения кладите в .git/info/exclude или глобальный игнор.
Можно ли иметь несколько файлов .gitignore?
Да, .gitignore можно положить в любую подпапку, и его правила действуют относительно этой папки, дополняя корневые.
Как добавить в коммит игнорируемый файл?
Используйте git add -f путь/к/файлу; после этого файл отслеживается, и .gitignore на него больше не влияет.
Как посмотреть все игнорируемые файлы в проекте?
Выполните git status --ignored или git ls-files --others --ignored --exclude-standard.
Как временно перестать отслеживать изменения в закоммиченном файле?
Для этого есть git update-index --skip-worktree файл, но это локальная настройка и не замена .gitignore.
Эта тема подробно разобрана с практикой в курсе «Git с нуля до уверенного разработчика».
Перейти к курсу