Зачем игнорировать файлы
.gitignore — это обычный текстовый файл в корне проекта, где вы построчно перечисляете файлы и папки, которые Git должен не замечать. Они не показываются в git status и не попадают в коммиты, даже когда вы добавляете всё сразу командой git add .. Так в историю не попадают мусор, личные черновики и пароли. Вы создадите такой файл для визитки и сделаете им шестой коммит.
До сих пор мы добавляли файлы по одному, поэтому в пяти коммитах лежит только нужное. Но скоро рядом с кодом появится лишнее, и одно неосторожное git add . отправит его в историю.
Простыми словами
Представьте список «не брать» перед поездкой: вы собираете чемодан и каждую вещь сверяете со списком. Git делает то же с папкой проекта: перед тем как предложить вам файл для git add, он заглядывает в .gitignore и пропускает всё, что там названо.
Что обычно игнорируют
- Мусор операционной системы:
.DS_Store(его создаёт Finder на Mac),Thumbs.db(миниатюры в Windows). Вы их не создавали и не заметите, а в репозитории они бесполезны. - Настройки редактора: папка
.vscode/хранит параметры VS Code именно на вашем компьютере. - Логи и временные файлы:
*.log, файлы отладки, кеши. Они меняются при каждом запуске и только раздувают историю. - Личные черновики: у нас это папка
notes/с идеями для визитки. Для вас это рабочие заметки, а не часть сайта. - Секреты: файл
.envс паролями, ключи доступа, токены. Это самая важная причина.
Секреты и история: удалить мало
Если пароль или ключ попал в коммит, удалить файл следующим коммитом недостаточно: старый коммит хранит его навсегда, и любой, кто увидит историю, прочитает пароль. Особенно это опасно, когда репозиторий публичный (а визитку мы скоро выложим на GitHub).
Поэтому записывайте файлы с секретами в .gitignore ДО первого коммита, где они могли бы появиться. А если секрет уже утёк, считайте его скомпрометированным: сразу смените пароль или перевыпустите ключ.
Синтаксис .gitignore
Допустим, в папке проекта появились папка notes с файлом ideas.txt (наши идеи) и лог debug.log (в практике ниже вы создадите их сами). Что скажет Git?
$ git status
On branch main
Untracked files:
(use "git add <file>..." to include in what will be committed)
debug.log
notes/
nothing added to commit but untracked files present (use "git add" to track)
Оба имени числятся неотслеживаемыми (Untracked files), и при первом же git add . они попадут в коммит. Создайте в корне проекта файл с именем .gitignore (точка в начале обязательна) и впишите в него такие строки:
# Мусор операционных систем
.DS_Store
Thumbs.db
# Настройки редактора
.vscode/
# Логи
*.log
# Личные черновики
notes/
Разбор по строкам
# Мусор операционных систем— строка, которая начинается с#, — комментарий. Git её пропускает, она нужна людям.- Пустая строка — просто разделитель, ни на что не влияет.
.DS_StoreиThumbs.db— точные имена файлов. Правило действует на любой глубине: файл в подпапке тоже будет проигнорирован..vscode/— косая черта в конце означает «это папка»: игнорируется папка целиком вместе со всем, что внутри.*.log— звёздочка заменяет любое количество любых символов, поэтому правило ловитdebug.log,error.logи вообще любой файл с расширением.log.notes/— наша папка с черновиками, тоже целиком.
Посмотрим, что изменилось:
$ git status
On branch main
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
nothing added to commit but untracked files present (use "git add" to track)
debug.log и notes/ исчезли из списка. Остался только сам .gitignore: это обычный файл проекта, его нужно коммитить, чтобы правила действовали у всех, кто получит репозиторий.
Шпаргалка по записи правил
| Запись | Что игнорируется |
|---|---|
*.log | любые файлы с расширением .log в любой папке |
notes/ | папка notes (на любой глубине) со всем содержимым |
/build | только build в корне проекта; косая черта в начале привязывает правило к месту, где лежит .gitignore |
!important.log | восклицательный знак отменяет игнорирование: important.log останется в Git, хотя *.log его бы скрыл (правило-исключение пишите ПОСЛЕ общего) |
**/temp | папка или файл temp на любой глубине; двойная звёздочка означает «любые вложенные папки» |
# текст | комментарий |
Исключение через ! не сработает, если скрыта целая папка: файл из игнорируемой папки вернуть нельзя. Все тонкости записи описаны в документации: gitignore.
Как проверить, что правило работает
Когда правил много, непонятно, какое сработало. Для этого есть команда git check-ignore (check — «проверить», ignore — «игнорировать») с флагом -v (verbose, «подробно»). Ей передают пути, а она отвечает, какая строка какого файла их игнорирует:
$ git check-ignore -v notes/ideas.txt debug.log
.gitignore:12:notes/ notes/ideas.txt
.gitignore:9:*.log debug.log
$ git check-ignore -v index.html
$
Разбор по строкам
.gitignore:12:notes/— через двоеточия: файл с правилом, номер строки в нём (12-я) и сама строка. Дальше (после табуляции) — путь, к которому применили это правило..gitignore:9:*.log— дляdebug.logсработала девятая строка.- Для
index.htmlкоманда молчит: ни одно правило его не касается. Так вы убедитесь, что случайно не спрятали нужное.
А git status --ignored добавит к обычному выводу раздел Ignored files со всем скрытым.
Готовые шаблоны и общий список
Писать .gitignore с нуля не обязательно. На GitHub есть коллекция готовых файлов для разных языков и инструментов: github.com/github/gitignore. Когда в вашем проекте появятся зависимости или сборка, откройте шаблон под свой инструмент и скопируйте нужное. Пока у нас достаточно собственных пяти строк.
Есть и второй уровень: глобальный файл исключений для мусора ОС, который появляется в любом проекте. Его один раз подключают так:
$ git config --global core.excludesFile ~/.gitignore_global
Всё, что вы запишете в ~/.gitignore_global (в том же формате), игнорируется во всех репозиториях на вашем компьютере. Мусор ОС мы всё равно оставим и в проектном файле: он защитит репозиторий и от коллег, у которых глобального файла нет.
Файл уже в Git: git rm --cached
Самая частая путаница: «записал в .gitignore, а Git всё равно следит за файлом». .gitignore действует только на неотслеживаемые файлы. Если файл уже попал в коммит, Git считает его частью проекта и продолжает показывать изменения, какие бы правила вы ни написали.
Чтобы увидеть это самим и не мусорить в визитке, сделаем отдельный учебный репозиторий. Отдельная папка нужна только для опыта, после него к ней можно не возвращаться:
$ cd ~/projects
$ mkdir ignore-demo
$ cd ignore-demo
$ git init -b main
$ echo "# demo" > README.md
$ echo "start" > app.log
$ git add .
$ git commit -m "Первый коммит"
Мы случайно закоммитили лог. Теперь «исправим» это обычным способом и допишем в файл ещё строку, чтобы Git увидел изменение:
$ echo "*.log" > .gitignore
$ echo "more" >> app.log
$ git status
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: app.log
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
no changes added to commit (use "git add" and/or "git commit -a")
Правило *.log есть, но app.log по-прежнему modified. Нужно сказать Git: «перестань отслеживать этот файл, но с диска не удаляй». Для этого служит git rm --cached (rm — remove, «удалить»; --cached — «только из индекса»):
$ git rm --cached app.log
rm 'app.log'
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: app.log
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
$ git add .gitignore
$ git commit -m "Игнорировать логи"
$ git status
On branch main
nothing to commit, working tree clean
$ ls
README.md app.log
Разбор по строкам
rm 'app.log'— Git убрал файл из индекса. Слово «rm» не пугайтесь: на диске файл остался, это видно поlsв конце.deleted: app.logв разделеChanges to be committed— из следующего коммита файл исчезнет. Для истории это «удаление», но рабочая копия цела.- После коммита
git statusчистый:app.logпо-прежнему лежит в папке, но теперь он неотслеживаемый, и правило*.logего скрывает.
Откуда мы уже встречали git rm --cached
В модуле про первые коммиты git status подсказывал именно эту команду: перед самым первым коммитом он пишет use "git rm --cached <file>..." to unstage. Там смысл тот же: «убрать файл из индекса, оставив на диске». После первого коммита для такой цели есть более новая команда git restore --staged, о ней в следующем уроке.
Файл остаётся в старых коммитах
git rm --cached убирает файл только из будущих коммитов. Старые коммиты хранят его содержимое по-прежнему. Для логов это не страшно, а для паролей — опасно, поэтому секреты в Git не кладут никогда (см. выноску выше).
Практика у себя
Теперь сделаем шестой коммит в визитке. Все команды — в папке проекта.
- Проверьте старт. Перейдите в проект и убедитесь, что всё чисто:
cd ~/projects/portfolio, затемgit status— должно бытьnothing to commit, working tree clean, аgit log --oneline— пять коммитов. - Создайте «мусор». Выполните три команды (в Windows они работают в Git Bash):
mkdir notesprintf 'Идеи для визитки:\n- добавить фото\n- рассказать про проекты\n' > notes/ideas.txttouch debug.log
Теперьgit statusпоказывает вUntracked filesдве строки:debug.logиnotes/. - Создайте файл
.gitignoreв корне проекта (в VS Code: меню File, пункт New File; при сохранении назовите файл.gitignore) и вставьте содержимое из раздела про синтаксис, все 12 строк. Сохраните. - Проверьте правила. Выполните
git status: в списке должен остаться один.gitignore. Затемgit check-ignore -v notes/ideas.txt debug.log: две строки с номерами 12 и 9, как в примере выше. - Закоммитьте.
git add .gitignore, затемgit commit -m "Добавить .gitignore". В ответ Git напишет1 file changed, 12 insertions(+). - Уберите лог. Лог нужен был только для опыта:
rm debug.log. Папкуnotesоставьте: теперь она в историю не попадёт.
Итоговая история должна выглядеть так (хеши у вас будут свои):
$ git log --oneline
12d081f (HEAD -> main) Добавить .gitignore
284ecf7 Исправить опечатку в заголовке
cb00bb8 Добавить раздел «Мои проекты»
f58d529 Добавить README
8c23940 Добавить стили
027a150 Добавить главную страницу
Проверьте себя
git log --onelineпоказывает шесть коммитов, последний — «Добавить .gitignore».git statusсообщаетnothing to commit, working tree clean, хотя папкаnotesлежит на диске.git check-ignore -v notes/ideas.txtотвечает строкой, где упоминаетсяnotes/.- Вы можете объяснить, почему
.gitignoreне помогает для файла, который уже попал в коммит, и чем это лечится.
Частые ошибки
Правило не работает: файл по-прежнему в git status. Чаще всего файл уже отслеживается (был в коммите раньше). Проверьте: git ls-files debug.log выведет имя, если файл отслеживается. Лечение — git rm --cached и коммит, как выше.
Файл называется .gitignore.txt. Это бывает в Windows: проводник и некоторые редакторы дописывают расширение. Git ищет ровно .gitignore. Создавайте файл в VS Code или командой touch .gitignore, а если сохраняете из другой программы, выбирайте тип файла «Все файлы». Проверка: ls -a должен показать .gitignore без хвоста.
Закоммитили пароль. Удалить файл следующим коммитом мало, история помнит его. Смените пароль или ключ и только потом наводите порядок.
Что важно запомнить
.gitignore— файл в корне проекта: по строке на правило (*.log,notes/,/build,!важный.log,#для комментариев).- Он скрывает только неотслеживаемые файлы. Для уже отслеживаемого сначала
git rm --cached <файл>и коммит. git check-ignore -v <путь>показывает, какая строка сработала;git status --ignored— список скрытого.- Сам
.gitignoreкоммитят; секреты (.env, ключи) вписывают в него до первого коммита. - Шаблоны для языков: github.com/github/gitignore; общий список для всех проектов —
core.excludesFile.
Теперь в историю попадает только нужное. Но ошибаться мы будем всё равно: правка окажется неудачной, в индекс уйдёт лишний файл, в подписи коммита обнаружится опечатка. Как отменить такие вещи, не потеряв остальную работу, разберём в следующем уроке.