Глиф Учебники

Урок 8. Файл .gitignore: что не класть в репозиторий

Курс «Git» · урок 8 из 9 · 4 минуты чтения

Не всё, что лежит в папке проекта, нужно хранить в истории. Мусор и секреты в репозитории мешают всем: история раздувается, git status показывает сотни лишних файлов, а пароль из настроек виден каждому, кто получил копию. Список того, что Git должен не замечать, пишут в файл .gitignore.

Что обычно исключают

Создайте .gitignore

Файл называется ровно .gitignore — с точкой в начале и без расширения — и лежит в корне репозитория, рядом с папкой .git. Создайте его в редакторе или командой touch .gitignore и впишите правила, по одному в строке:

Текст
# Журналы и временные файлы
*.log
*.tmp

# Зависимости и сборка
node_modules/
/build/

# Секреты
.env

Сам .gitignore добавляют в репозиторий как обычный файл: git add .gitignore и коммит. Тогда правила действуют у всех, кто работает с проектом.

В Windows Проводник и Блокнот иногда дописывают к имени .txt, и получается .gitignore.txt, который Git не читает. Включите показ расширений в Проводнике или создайте файл командой в Git Bash.

Правила шаблонов

ЗаписьЧто исключает
secret.txtФайл или папку с таким именем на любом уровне
*.logВсе файлы с расширением .log везде
temp/Папки temp на любом уровне вместе с содержимым (но не файл temp)
/build/Только папку build в корне репозитория, не src/build
docs/*.pdfPDF прямо в docs, но не в docs/api
!keep.logИсключение из правила выше: keep.log снова отслеживается
# текстКомментарий
.gitignore *.log *.tmp node_modules/ /build/ .env папка проекта .gitignore в Git .env .env README.md в Git app.log *.log build/ /build/ node_modules/ node_modules/ src/ main.js в Git debug.log *.log build/ в Git — не в корне
По правилам из примера Git не замечает .env, node_modules, файлы *.log в любой папке и build только в корне, а src/build, исходники и сам .gitignore остаются в репозитории.

Правило с ! не работает, если исключена вся папка, в которой лежит файл: после logs/ строка !logs/k.log ничего не вернёт. Git не заглядывает в исключённые папки. Чтобы исключить всё в папке, кроме одного файла, пишут logs/* и затем !logs/k.log.

logs/ !logs/k.log logs/ logs/ app.log k.log Не работает в исключённую папку Git не заглядывает logs/* !logs/k.log logs/ app.log logs/* k.log в Git Работает исключено всё в папке, кроме k.log
После правила logs/ исключена вся папка, и !logs/k.log не возвращает файл, а после logs/* исключены файлы внутри папки, и k.log снова отслеживается.

Пример для проекта на Python

Текст
__pycache__/
*.pyc
.venv/
.env
.idea/
.vscode/

Готовые списки для разных языков и редакторов предлагают и хостинги — например, GitHub при создании репозитория. Это хорошая основа, которую потом дополняют своим.

Файл уже в репозитории — .gitignore «не работает»

.gitignore действует только на неотслеживаемые файлы. Если файл уже был в коммите, Git продолжит следить за ним, что бы ни было написано в .gitignore. Его нужно убрать из индекса, оставив на диске:

Терминал
$ git rm --cached .env
rm '.env'
$ git commit -m "Файл .env больше не отслеживается"

Для папки — с ключом -r: git rm -r --cached build. Подробнее — в справке Как удалить файл из репозитория, но оставить на диске.

Удаление из индекса не стирает файл из прошлых коммитов: кто получит копию репозитория, увидит его в истории. Если туда попал пароль или ключ, смените его, а как почистить историю — в справке Как убрать пароль из истории Git.

Файл .env уже в коммите — правило .env его не скрывает рабочая папка .env индекс .env коммиты .env git rm --cached .env и коммит рабочая папка индекс коммиты .env остался на диске нет убран из индекса новые — без .env старые — с .env попал пароль — смените его: старые коммиты есть в каждой копии
Уже отслеживаемый .env правило из .gitignore не скрывает; git rm --cached убирает его из индекса и новых коммитов, файл остаётся на диске, а в старых коммитах он есть по-прежнему.

Почему файл игнорируется

Иногда наоборот: файл нужен, а Git его не видит. Какое правило виновато, показывает git check-ignore -v:

Терминал
$ git check-ignore -v logs/k.log
.gitignore:2:*.log    logs/k.log

Файл .gitignore, строка 2, правило *.log. Если команда ничего не вывела — файл не игнорируется.

Свои правила, которые не нужны остальным

Bash
git config --global core.excludesFile ~/.gitignore_global

Пустые папки

Git хранит файлы, а не папки: пустая папка в коммит не попадёт. Если папка нужна в проекте (например, logs для журналов программы), в неё кладут пустой файл — по обычаю его называют .gitkeep — и добавляют его.

Коротко

Проверьте себя

1. Файл config.ini уже есть в коммитах. Его дописали в .gitignore, но git status продолжает его показывать. Почему?
2. Что исключит правило /build/?
3. Как узнать, какое правило игнорирует файл?
4. Почему файл .env с паролями не коммитят даже в закрытый репозиторий?