Короткий ответ
Нужно немедленно отозвать и перевыпустить скомпрометированный токен (это главный и срочный шаг, не зависящий от истории Git), проверить логи доступа на предмет использования токена посторонними, затем переписать историю репозитория (git filter-repo/BFG), форсированно обновить удалённую ветку и попросить всех участников пересоздать локальные клоны; удаление файла новым коммитом токен из истории не убирает.
Как это работает подробнее
Git хранит полную историю объектов, и удаление файла в новом коммите лишь убирает его из последнего снимка — сам файл с секретом остаётся доступен через старые коммиты (git show <hash>:path, git log -p), а также мог уже быть склонирован другими людьми, зеркалирован CI-системой или проиндексирован сервисами сканирования публичных репозиториев.
Пример кода
# 1. Немедленно: отозвать и перевыпустить токен на стороне сервиса (вне Git)
# 2. Найти, где и когда секрет попал в историю
git log --all -p -- config/secrets.yaml | grep -n "API_TOKEN"
# 3. Переписать историю, убрав файл из всех коммитов
git filter-repo --path config/secrets.yaml --invert-paths
# 4. Форсированно обновить удалённый репозиторий (после согласования с командой)
git push origin --force --allЧто использовать на практике
- Рекомендация. порядок действий важен — сначала ротация секрета (это снимает реальный риск немедленно), затем расследование (не использовался ли токен уже кем-то посторонним, по логам аудита API), и только потом "косметическая" очистка истории репозитория, которая нужна скорее для гигиены и соответствия политикам, чем для безопасности как таковой, раз токен уже не действителен.
Подводные камни
- Ошибка. считать переписывание истории достаточной мерой и не ротировать сам секрет — тогда любой, кто уже успел склонировать репозиторий до очистки, сохраняет рабочий токен; переписывать историю в общей ветке без согласования с командой, что ломает чужие локальные ветки и открытые pull request'ы, привязанные к старым хэшам коммитов.