Урок курса

Почему ignore не помог уже сохранённому файлу

Git и GitHub с нуля: бесплатный курс с практикой

В прошлом уроке выяснилось, что шаблон в .gitignore не трогает уже отслеживаемые файлы. Если notes.local.txt уже есть в индексе, добавление его имени в .gitignore ничего не меняет — Git продолжает за ним следить. Команда git rm --cached удаляет запись из индекса, сохраняя рабочий файл на диске.

Почему .gitignore не останавливает отслеживание уже закоммиченного файла

Git разделяет файлы на два принципиально разных класса: отслеживаемые (tracked) — те, чья запись есть в текущем индексе, — и неотслеживаемые (untracked) — те, которых в индексе нет.

.gitignore влияет только на второй класс. Когда Git встречает в рабочей папке файл, которого нет в индексе, он проверяет правила игнорирования и, если путь совпадает с шаблоном, перестаёт его показывать в выводе git status как untracked. Файл просто не виден.

Но если файл уже попал в индекс — через git add и коммит — у Git есть его снимок. Правило в .gitignore на этот случай не распространяется: индексная запись не исчезает от того, что имя файла добавлено в .gitignore. Git продолжает сравнивать рабочий файл с тем, что записано в индексе, и сообщает об изменениях как обычно.

Поэтому в нашем учебном репозитории картина такая: notes.local.txt закоммичен, запись о нём есть в индексе. Добавляем в .gitignore строку notes.local.txt — и ничего не меняется. Если открыть notes.local.txt, отредактировать его и выполнить git status, Git честно сообщит modified: notes.local.txt. Правило игнорирования здесь не при чём: файл отслеживаемый, и это определяется индексом, а не историей и не .gitignore.

git rm --cached: удаление записи из индекса без удаления файла с диска

git rm --cached <путь> удаляет запись о файле из индекса Git. Рабочий файл при этом остаётся нетронутым — он никуда не исчезает.

После выполнения команды:

  • Запись пути исчезает из индекса — Git больше не считает этот файл отслеживаемым.
  • Файл на диске остаётся с тем содержимым, которое было до команды.
  • git status показывает изменение как подготовленное к коммиту: deleted: notes.local.txt в разделе «Changes to be committed».

Пример выполнения:

git rm --cached notes.local.txt

Вывод:

rm 'notes.local.txt'

Git сообщает, что убрал путь из индекса — именно убрал запись, не файл. После этого git status покажет staged deletion. Если путь покрыт сохранённым правилом в .gitignore, оставшийся рабочий файл уже не показывается как untracked; для действия правила коммит не нужен. Подготовленное удаление из снимка остаётся в статусе до коммита. После него при отсутствии других правок статус будет чистым.

Что произойдёт без флага --cached

git rm notes.local.txt (без --cached) удаляет файл и из индекса, и из рабочей папки. Файл исчезнет с диска. Это деструктивная операция, и отменить её без дополнительных команд не получится. Флаг --cached обязателен именно тогда, когда нужно сохранить файл на диске и только убрать его из отслеживания.

Полная последовательность: добавить правило и убрать файл из отслеживания одним коммитом

Распакуйте выданный git_practice.zip в новую пустую папку. Откройте терминал в этой папке, куда извлечён архив, и перейдите в готовый учебный репозиторий:

cd "git_practice/prepared/tracked_local_file"
git config user.name "Учебный автор"
git config user.email "learner@example.invalid"
git status
git log --oneline

В tracked_local_file уже существует .git: повторный git init не нужен. Обе команды config задают локальную личность автора именно для нового коммита в этом репозитории; настройки другой рабочей папки сюда не переносятся. До правок убедитесь, что status чистый и log показывает два исходных коммита.

Исходное состояние в учебном репозитории git_practice/prepared/tracked_local_file: два коммита в ветке main — «Первый справочник» (README.md) и «Добавить локальные заметки» (notes.local.txt). Файл .gitignore отсутствует. git status показывает чистое состояние: notes.local.txt отслеживается, но не изменён, поэтому в выводе он не появляется.

Шаги для исправления ситуации:

1. Отредактировать notes.local.txt

Открыть файл в редакторе, добавить строку «Учебная правка» и сохранить. Теперь git status покажет:

Changes not staged for commit:
  modified:   notes.local.txt

Это подтверждает: файл отслеживается, и .gitignore ещё не существует.

2. Создать .gitignore

Открыть редактор, создать новый файл .gitignore в той же папке, ввести одну строку:

notes.local.txt

Сохранить. git status по-прежнему показывает modified: notes.local.txt и добавляет Untracked files: .gitignore. Правило уже прочитано Git при обработке рабочей папки, но на отслеживаемый файл оно не влияет.

3. Подготовить оба изменения к коммиту

git add .gitignore
git rm --cached notes.local.txt

Порядок этих двух команд не важен — главное, что оба изменения должны быть staged до коммита. После выполнения git status покажет:

Changes to be committed:
  new file:   .gitignore
  deleted:    notes.local.txt

4. Создать коммит

git commit -m "Убрать notes.local.txt из отслеживания"

5. Проверить результат

git status

Вывод: nothing to commit, working tree clean. Открыть notes.local.txt в редакторе — файл на месте, строка «Учебная правка» сохранена. Git больше не следит за этим файлом, а .gitignore скрывает его от git status как неотслеживаемый путь, совпадающий с правилом.

Для одного коммита с правилом и прекращением отслеживания нужны оба изменения: git add .gitignore и git rm --cached notes.local.txt. Только добавление .gitignore в индекс не уберёт запись notes.local.txt. После git rm --cached оставшийся рабочий файл будет показан как untracked, если для него нет действующего правила игнорирования. Но сохранённый рабочий .gitignore применяется сразу, даже когда сам он ещё untracked, не добавлен в индекс и не закоммичен. Поэтому совпадающий с его правилом notes.local.txt уже скрыт как untracked; до коммита в статусе остаётся подготовленное удаление прежнего снимка.

Добавление .gitignore в индекс и общий коммит сохраняют правило вместе с прекращением отслеживания в истории проекта, чтобы правило можно было передать вместе с этой версией. Они не включают локальное игнорирование.

Три независимых слоя: текущий индекс, рабочий файл и исторический снимок

После коммита «Убрать notes.local.txt из отслеживания» результат выглядит так — и важно не смешивать три разных наблюдения.

Текущий индекс — записи о notes.local.txt больше нет. Git не отслеживает этот путь. Именно поэтому git status показывает чистое состояние: нечего сравнивать.

Рабочий файл — notes.local.txt существует на диске с той строкой, которую мы добавили в редакторе. git rm --cached не тронул его содержимое. Дальнейшие правки этого файла останутся невидимыми для git status, потому что путь покрыт правилом в .gitignore и не отслеживается.

Исторический снимок — в коммите «Добавить локальные заметки» notes.local.txt сохранён с тем содержимым, которое было на момент того коммита. Никакая последующая операция с индексом не меняет уже созданные коммиты. Содержимое из старого снимка можно прочитать командой:

git log --oneline

Выбрать ID коммита «Добавить локальные заметки» из вывода, затем:

git show <этот-ID>:notes.local.txt

Git вернёт содержимое файла именно из того снимка — без строки «Учебная правка», потому что она была добавлена уже после того коммита. Синтаксис <ID>:<путь> означает: «содержимое пути в указанном коммите».

Эти три слоя независимы. «Файл не отслеживается сейчас» не означает «файл никогда не существовал в истории». История не переписывается: старый снимок остаётся доступным через git show столько, сколько существует репозиторий.

Задача 1

notes.local.txt находится в текущем индексе и последнем коммите. В файле добавили новую строку, но add не выполняли. Затем сохранили правило notes.local.txt в .gitignore. Как это повлияет на отслеживание именно notes.local.txt?

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 2

Отслеживаемый notes.local.txt нужно исключить из будущего снимка, сохранив файл на диске. Правило игнорирования уже записано. Коммит ещё не выполнен. Какая команда делает нужное изменение индекса?

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 3

Практика: распакуйте полный git_practice.zip в отдельную новую папку. Откройте git_practice/prepared/tracked_local_file; это уже готовый репозиторий. Через редактор измените notes.local.txt, проверьте status, создайте .gitignore с именем этого файла и снова проверьте status. Подготовьте правила, уберите notes.local.txt из индекса с сохранением файла на диске и создайте коммит. Проверьте наличие рабочего файла, status и старый коммит через show с ID из своей истории. Запишите состояние индекса и файла на диске до и после операции, ID нового коммита и свидетельство из старого коммита. Письменно объясните коллеге, почему одного правила игнорирования недостаточно и почему старые снимки сохранились.

Платформа проверяет только ответ ниже; действия в своём репозитории и письменные ответы вы проверяете самостоятельно.

В отдельном контрольном случае файл уже убрали из индекса через rm --cached, но правило игнорирования для него не добавляли. Затем записали удаление коммитом. Файл на диске не меняли и не удаляли. Как он будет показан в обычном status?

Выберите один вариант
Без регистрации · результат не сохраняется

Продолжить с сохранением прогресса

Перейдите к уроку в учебном кабинете.

Перейти к интерактивному уроку