Инструкция

Файл .gitignore: как исключить файлы из Git и убрать уже добавленные

Обновлено: · Skillaria.Top

Файл .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/*.pdfpdf прямо в docs, но не в docs/old/
docs/**/*.pdfpdf в docs и всех вложенных папках
**/temptemp в любой папке
!keep.logисключение: не игнорировать keep.log
file?.txt? — один любой символ
[ab].txta.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 с нуля до уверенного разработчика».

Перейти к курсу