TL;DR: если .gitignore не работает, файл почти наверняка уже отслеживается. Git игнорирует файлы, которые никогда не видел, — файл в индексе невосприимчив к любому вашему правилу. Проверка правдой: git check-ignore -v <path>; молчание означает, что путь отслежен и ни одно правило не действует. Лечение: git rm --cached <path>, коммит — и правило начинает работать с этого коммита и дальше. Порядок правил, ловушки с отрицанием и ложные улики от VS Code объясняют оставшиеся случаи.
Почему .gitignore не работает?
Один механизм покрывает большинство случаев: файл закоммитили раньше, чем появилось правило. .gitignore — не фильтр, прячущий файлы от git, а правило о том, что git add должен подбирать из неотслеженного состояния. Попав в индекс, файл отслеживается по содержимому вечно, пока вы явно не снимете его с учёта. Правка .gitignore задним числом на отслеженные файлы не влияет — поэтому классическая последовательность «закоммитил .env, испугался, добавил .env в .gitignore, закоммитил снова» продолжает публиковать секрет при каждом пуше.
Это кусает всех, потому что git почти повсюду: опрос Stack Overflow 2022 года показал использование Git более чем у 93 % профессиональных разработчиков (survey.stackoverflow.co) — и каждый из них рано или поздно пишет правило для файла, закоммиченного на прошлой неделе.
Дальше в посте — меньшинство случаев: ошибки порядка правил, ловушки отрицания, краевые случаи папок и вопрос про IDE. Но сначала прогоните проверку из следующей секции — больше чем в девяти случаях из десяти она закрывает расследование.
Как узнать, какое правило gitignore срабатывает для файла?
git check-ignore — диагностический инструмент, и его молчание — тоже диагноз:
# Печатает сработавшее правило + файл + номер строки, если правило действует
git check-ignore -v debug.log
# .gitignore:3:*.log debug.log
# Ничего не печатает, если правило не действует — файл отслежен (или правил нет)
git check-ignore -v src/.env
# (тишина = .gitignore этот путь не игнорирует, что бы вы ни написали)
# Коды выхода: 0 = игнорируется, 1 = не игнорируется — годится для скриптов
git check-ignore -q debug.log && echo "ignored" || echo "tracked or unruly" Разбор вывода -v: источник правила (.gitignore, .git/info/exclude или ваш глобальный файл), затем номер-строки:шаблон, затем путь. Если последнее правило вас удивило, вспомните приоритет: побеждает последнее совпавшее правило, поэтому !important.log после *.log возвращает один файл.
Почему gitignore не работает для уже закоммиченных файлов?
Снимите файл с учёта, оставьте на диске, закоммитьте удаление:
# Снять один файл с учёта (локальная копия выживает — --cached трогает только индекс)
git rm --cached .env
git commit -m "stop tracking .env"
# Проверить, что правило теперь действует
git check-ignore -v .env С этого коммита путь принадлежит .gitignore: правки больше не видны в git status, а git add . не подберёт файл снова. Но в истории файл остаётся — если это был секрет, удаления из последнего коммита мало. Единственное настоящее лекарство — ротация учётных данных; переписывание истории — косметика (а отмена последнего коммита помогает лишь пока плохой коммит ещё на кончике ветки).
Для репозитория, набитого ранее закоммиченным хламом — артефактами сборки, мусором редактора, ранним node_modules — массовое снятие с учёта умещается в две строки:
git rm -r --cached .
git add .
git commit -m "apply .gitignore to tracked files" Это пересобирает индекс по текущим правилам: игнорируемые пути выпадают, всё прочее добавляется заново без изменений. Diff выглядит драматично (тысячи удалений), но с диска не стирает ничего. Если цель — именно удалить эти файлы, а не только снять с учёта, это территория git clean -fdx: см. git remove untracked files, безопасно.
Git игнорирует файлы, которые никогда не видел. Файл в индексе невосприимчив к
.gitignore— ни одно правило его не «развидит».
Почему gitignore не работает для папки?
Три папочные ловушки:
1. Слэш на конце важен для замысла, а не для совпадения. build и build/ оба совпадают с каталогом, но build/ документирует, что вы имеете в виду только каталог — файл с именем build переживёт его. Правда, на повторном включении симметрия ломается (следующая ловушка).
2. Отрицание не спасёт файлы внутри исключённого каталога. Документация git недвусмысленна: «невозможно снова включить файл, если исключён родительский каталог этого файла» (git-scm.com/docs/gitignore). Это решение ради производительности — git пропускает исключённые каталоги целиком, не заглядывая внутрь. Поэтому это не работает:
build/
!build/keep.me # мёртвое правило — git никогда не заглянет в build/ Лечение — исключать содержимое, а не каталог:
build/*
!build/keep.me # работает — сам build/ остаётся открыт для осмотра 3. Вложенные .gitignore побеждают в своей зоне. Правила из subdir/.gitignore перекрывают корневой файл для путей внутри subdir. Когда git check-ignore -v называет неожиданный источник игнора — обычно вот почему.
Почему gitignore не работает в VS Code?
Почти никогда по причинам VS Code. Панель Source Control читает тот же индекс, что и git, поэтому симптом тот же: файл уже закоммичен, и никакой перезапуск IDE индекс не изменит. Две реальности около VS Code знать стоит:
- Серый в Explorer = игнорируется; оранжевый/жёлтый = отслежен с изменениями. Файл, отображающийся как изменённый после того, как вы его игнорировали, — подтверждение, что он отслежен: применяйте
git rm --cachedвыше. - Отсутствие
.gitignoreв списке изменённых файлов Explorer — признак, что правило работает: файл просто никогда не появится как untracked. Часто жалуются «VS Code игнорирует мой gitignore», когда CLIgit statusрасходится с устаревшим видом SCM: перезагрузите окно (Cmd/Ctrl+Shift+P→ «Reload Window»), прежде чем винить git.
.gitignore против .git/info/exclude и глобального файла: что когда?
| Файл | Область действия | Коммитится? | Для чего |
|---|---|---|---|
.gitignore (репозиторий) | Все, кто клонирует | Да | Артефакты сборки, зависимости, .env — общие правила |
.git/info/exclude | Только ваш клон | Нет | Личный мусор: .scratch/, droppings редактора |
core.excludesFile (глобальный) | Все ваши репозитории | Нет | Мусор ОС: .DS_Store, Thumbs.db, *.swp |
.gitignore + отрицание | Репозиторий | Да | Повторное включение исключений в отслеживаемых конфигах |
Глобальный файл — тот, который большинство разработчиков не настраивают, а зря:
git config --global core.excludesFile ~/.gitignore_global
printf '.DS_Store\nThumbs.db\n*.swp\n' >> ~/.gitignore_global Правило, которое стоит забрать себе: если правило полезно всей команде, оно принадлежит репозиторию; если только вам — exclude или глобальному файлу. Коммит личных игнор-правил — вот как .gitignore разрастается до 300 строк, в которых никто не помнит, какая половина ещё жива.
Как игнорировать изменения уже отслеженного файла?
Иногда отслеженный файл нужен (шаблон конфига, настройки IDE), но локальные правки должны перестать мелькать в git status. Два флага git update-index, ни один из которых не место в командном процессе:
git update-index --skip-worktree config/local.dev # локальные правки замолкают
git update-index --no-skip-worktree config/local.dev # ...и обратно --skip-worktree — защищаемый вариант: он говорит «моя локальная версия расходится намеренно». Его кузен --assume-unchanged — обещание производительности («этот файл не изменится»), а не механизм игнора, и git может молча его нарушить. Оба флага громко падают при pull, если upstream тоже менял файл; прочные ответы — локальный конфиг через exclude с самого начала или файл-шаблон (config.example), который git отслеживает, а вы копируете.
Проверка gitignore за 30 секунд
git check-ignore -v <path> # какое правило? (тишина = отслежен, правила нет)
git ls-files --error-unmatch <path> # вообще отслеживается?
git rm --cached <path> # снять с учёта, оставить на диске
git commit -m "stop tracking <path>"
git check-ignore -v <path> # правило теперь видно Диагностика, снятие с учёта, проверка. За каждой жалобой «gitignore not working» стоит один файл в двух ролях — отслеженный с одной стороны индекса, игнорируемый с другой, — и один флаг --cached снимает вторую роль.
FAQ
Почему .gitignore не работает?
В большинстве случаев файл уже отслеживается. Git игнорирует только неотслеженные файлы; файл в индексе невосприимчив к .gitignore, пока вы не снимете его с учёта через git rm --cached и не закоммитите.
Как проверить, какое правило gitignore совпадает с файлом?
Выполните git check-ignore -v <path>. Команда печатает точную строку .gitignore и её номер, а при отслеживаемом файле без подходящего правила молча завершается.
git rm --cached удаляет мой локальный файл?
Нет. --cached убирает файл только из индекса; копия на диске остаётся. Закоммитьте удаление — файл станет неотслеженным, после чего начнёт действовать .gitignore.
Почему gitignore не может снова включить файл внутри игнорируемой папки?
Ради производительности Git пропускает исключённые каталоги целиком. Согласно документации git, невозможно снова включить файл, если исключён один из его родительских каталогов.
— mrsaynothing
Get the next one by email
One email per post. No spam, no algorithms.
what is this?Ollama не использует GPU? Чиним на Linux, Windows и в WSL
Нравятся заметки? Я зарабатываю этим на жизнь. нанять меня