linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Главы
  • How it works
  • Уроки
  • База знаний
  • Собеседование
home/git/kb/Безопасность/git-filter-repo

kb/security ── Безопасность ── advanced

git filter-repo: переписывание истории

Современная замена устаревшему `git filter-branch`. Переписывает историю на месте: удаляет файлы, меняет email авторов, заменяет строки. Используется для удаления секретов или огромных бинарей, которые попали в репо.

view as markdownaka: filter-repo, rewrite-history

git filter-repo - отдельный инструмент (не часть Git core, ставится отдельно). Полностью переписывает историю: каждый коммит пересоздаётся с другим деревом/метаданными. Хирургическая операция, использовать с осторожностью.

Замена git filter-branch, который официально объявлен deprecated с Git 2.24: filter-branch медленный и легко ошибиться. filter-repo

  • быстрый (написан на Python, использует git fast-export) и безопасный (по умолчанию работает с чистым клоном).

Установка

bash
# macOS
brew install git-filter-repo
# Debian/Ubuntu
apt install git-filter-repo
# Pip
pip install git-filter-repo

Главные применения

Удалить файл из всей истории

Часто после случайно закоммиченного секрета. См. secret-scanning - сначала ротируй ключ, потом чистка.

bash
git filter-repo --path secrets.env --invert-paths

--invert-paths означает «удалить совпадения». Команда удалит secrets.env из всех коммитов истории.

Заменить строку

Если нужно убрать конкретное значение (a-la API-ключ), не файл:

bash
# Создать файл с правилами замены
cat > replace.txt <<EOF
AKIAIOSFODNN7EXAMPLE==>[REMOVED]
literal:my-secret-password==>[REMOVED]
regex:ghp_[a-zA-Z0-9]{36}==>[REMOVED]
EOF
git filter-repo --replace-text replace.txt

Это пройдёт по содержимому каждого коммита и заменит подходящие строки на placeholder.

Удалить большой файл

Кто-то закоммитил 500MB-датасет, репо распух. Удалить из истории:

bash
git filter-repo --strip-blobs-bigger-than 100M

Или конкретно по пути:

bash
git filter-repo --path dataset.csv --invert-paths

После - .git/ обычно физически распухший. Чтобы освободить место:

bash
git reflog expire --expire=now --all
git gc --aggressive --prune=now

Сменить email во всей истории

Закоммитил с личного email, хочешь - с рабочего:

bash
cat > mailmap.txt <<EOF
Your Name <work@company.com> <personal@gmail.com>
EOF
git filter-repo --mailmap mailmap.txt

Все коммиты с personal@gmail.com будут показаны как work@company.com. SHA коммитов изменится.

После filter-repo

Команда переписывает историю: SHA всех коммитов меняются. Последствия:

  • Все клоны теперь устаревшие. Никто не может просто git pull: история разошлась. Каждому нужно перейти на новый клон.
    • PR и issue, ссылающиеся на старые SHA, ломаются - старые коммиты не существуют.
  • Force push в remote. Очень внимательно: branch protection обычно блокирует, его нужно временно снять.
    • Резервная копия - обязательна. До запуска: git clone <url> backup-clone. Если что-то пошло не так - есть откуда восстановить.

Из-за этих последствий filter-repo - операция «один раз в год», не повседневная. Делается обычно командой, согласованно, с предупреждением всех.

Альтернативы

  • BFG Repo-Cleaner - Java-инструмент, ещё быстрее на больших репах. Менее гибкий: только удаление файлов/блобов, без замены текста.
  • Просто оставить и ротировать. Если речь о секрете в публичном репо - он уже скомпрометирован, чистка не отменяет утечки. Иногда правильно: ротировать ключ и зафиксировать урок, без переписывания истории.

Подводные камни

  • filter-repo по умолчанию работает только на свежем clone. Если запустишь в репо, где много remote - он откажется (через --force можно, но это сигнал «остановись, подумай»).
  • Submodules при filter-repo сохраняются, но если изменяются указатели - может потребоваться отдельная работа в каждом submodule. См. detached-head.
  • Очень большие репо (десятки GB) могут филтроваться часами. Запускать с nohup или в screen.
  • Tags локально переписываются, но в чужих клонах нет. На своей машине filter-repo обновит refs/tags: тег, указывавший на переписанный коммит, начнёт указывать на новый SHA; тег на удалённый коммит исчезнет. Но у коллег, которые ранее склонили репо, старые теги останутся локально - git fetch сам по себе их не удаляет. Нужно или git fetch --prune --prune-tags, или клон с нуля. На сервере не забудь снести устаревшие теги: git push origin :refs/tags/<tag>.

§ команды

bash
git filter-repo --path file.env --invert-paths

Удалить файл из всей истории

bash
git filter-repo --replace-text replace.txt

Заменить строки во всех коммитах

bash
git filter-repo --strip-blobs-bigger-than 100M

Удалить все большие файлы из истории

bash
git reflog expire --expire=now --all && git gc --aggressive --prune=now

Освободить место после filter-repo

§ см. также

  • secret-scanningПоиск секретов в репозиторииРегулярно сканировать репо на случайно закоммиченные секреты (API-ключи, пароли, токены). Главные инструменты: gitleaks, detect-secrets, trufflehog. Лучше - заранее, в pre-commit. После утечки - ротация ключа неотменимо, чистка истории необязательно.
  • gitignore.gitignoreФайл в корне репо со списком паттернов: что Git должен полностью игнорировать. Не путать с staging: уже tracked файлы .gitignore не трогает. Главная защита от случайного коммита секретов и мусора.
  • rebasegit rebaseПереписывает коммиты ветки, делая их потомками другого коммита. Создаёт новые SHA, история становится линейной. Безопасен только для веток, которые ещё никто, кроме автора, не видел.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки