Git: как убрать файл из репозитория, оставив его на диске
Чтобы перестать отслеживать файл и не удалять его с диска, выполните git rm --cached путь/к/файлу. Затем добавьте путь в .gitignore и сделайте коммит. Без этих двух шагов git продолжит показывать файл в изменениях.
Убрать один файл из репозитория
git rm --cached config/local.env # убрать из индекса, файл на диске остаётся
echo "config/local.env" >> .gitignore # чтобы git больше не предлагал его добавить
git add .gitignore
git commit -m "Перестать отслеживать config/local.env"Убрать папку целиком
git rm -r --cached build/
echo "build/" >> .gitignore
git add .gitignore
git commit -m "Убрать build/ из репозитория"Почему .gitignore не работает
Файл .gitignore действует только на неотслеживаемые файлы. Если файл уже попал в репозиторий, git продолжает следить за ним, как бы ни был записан шаблон. Проверить причину помогают две команды:
git ls-files config/local.env # если команда вывела путь, файл отслеживается
git check-ignore -v --no-index config/local.env # покажет правило, которое игнорирует файлЕсли первая команда выводит путь, нужен git rm --cached. Флаг --no-index нужен потому, что для уже отслеживаемого файла check-ignore без него молчит.
Обновить индекс по всему .gitignore
Когда в .gitignore добавили много правил и хочется разом убрать все лишние файлы, пересоберите индекс:
git rm -r --cached .
git add .
git commit -m "Применить обновлённый .gitignore"Секреты и история
git rm --cached убирает файл только из следующих коммитов. В старых коммитах он остаётся, поэтому пароли и ключи, попавшие в репозиторий, нужно считать скомпрометированными и заменить. Удалять их из истории нужно отдельными инструментами, например git filter-repo.
Частые вопросы
Чем отличается git rm от git rm --cached?
Без --cached git удаляет файл и из индекса, и с диска. С --cached файл остаётся на диске, пропадает только слежение за ним.
Как вернуть слежение за файлом?
Уберите правило из .gitignore и выполните git add путь/к/файлу, либо git add -f путь/к/файлу, если файл по-прежнему игнорируется.