$ sudo teach IT
Модуль 3 · Отмена и .gitignore · Урок 3.1

Файл .gitignore

Вы создадите .gitignore, который не пускает в историю мусор, личные черновики и секреты.

Теория + практика~20 минутНовичок.gitignoreигнорирование файлов

Зачем игнорировать файлы

.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 (точка в начале обязательна) и впишите в него такие строки:

Файл .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 не кладут никогда (см. выноску выше).

Практика у себя

Теперь сделаем шестой коммит в визитке. Все команды — в папке проекта.

  1. Проверьте старт. Перейдите в проект и убедитесь, что всё чисто:
    cd ~/projects/portfolio, затем git status — должно быть nothing to commit, working tree clean, а git log --oneline — пять коммитов.
  2. Создайте «мусор». Выполните три команды (в Windows они работают в Git Bash):
    mkdir notes
    printf 'Идеи для визитки:\n- добавить фото\n- рассказать про проекты\n' > notes/ideas.txt
    touch debug.log
    Теперь git status показывает в Untracked files две строки: debug.log и notes/.
  3. Создайте файл .gitignore в корне проекта (в VS Code: меню File, пункт New File; при сохранении назовите файл .gitignore) и вставьте содержимое из раздела про синтаксис, все 12 строк. Сохраните.
  4. Проверьте правила. Выполните git status: в списке должен остаться один .gitignore. Затем git check-ignore -v notes/ideas.txt debug.log: две строки с номерами 12 и 9, как в примере выше.
  5. Закоммитьте. git add .gitignore, затем git commit -m "Добавить .gitignore". В ответ Git напишет 1 file changed, 12 insertions(+).
  6. Уберите лог. Лог нужен был только для опыта: 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.

Теперь в историю попадает только нужное. Но ошибаться мы будем всё равно: правка окажется неудачной, в индекс уйдёт лишний файл, в подписи коммита обнаружится опечатка. Как отменить такие вещи, не потеряв остальную работу, разберём в следующем уроке.

На следующий урок