← На главную

git-filter-repo делает то, что медленному git filter-branch не под силу

21.07.2026 00:28 · hackernews

git-filter-repo — инструмент для полного переписывания истории Git, который пришёл на смену медленному и ограниченному git filter-branch. Сам проект Git теперь рекомендует именно его. Главное преимущество не только в скорости, но и в архитектуре: это одновременно готовая утилита командной строки и библиотека, на которой можно строить собственные инструменты перезаписи. Для базовой работы достаточно одного файла — скрипта git-filter-repo на python3, положенного в $PATH. Минимальные требования: git >= 2.36.0 и python3 >= 3.6.

Простая задача — вырезать из репозитория директорию src/, перенести все файлы в подпапку my-module/ и переименовать теги с префиксом my-module- — решается одной командой: git filter-repo --path src/ --to-subdirectory-filter my-module --tag-rename '':'my-module-'. BFG Repo Cleaner на такое в принципе не способен. Реализация на filter-branch превращается в многострочный shell-скрипт с массой оговорок: даже с --index-filter он на порядки медленнее, требует ручной зачистки старых объектов и тегов, не правит ссылки на устаревшие хеши в сообщениях коммитов, ломается на именах файлов с не-ASCII символами и спецзнаками, а флаг --prune-empty часто удаляет не те коммиты. Подход через fast-export/fast-import ещё сложнее и рискует повредить данные.

Разработчик спроектировал filter-repo, потому что ни один старый инструмент не давал нужной комбинации возможностей. Среди ключевых свойств: встроенный анализ репозитория для подсказки пользователю (флаг --analyze), удобные флаги для сохранения или удаления путей, простое переименование файлов и каталогов с проверкой на коллизии, принудительный отказ работать не на свежем клоне без --force, автоматическая сборка мусора после фильтрации, чёткое разделение старой и новой истории. Инструмент расширяется не через shell-команды, а через библиотечный API на python3, что ускоряет работу и делает скрипты переносимыми. Он поддерживает маппинг старых хешей коммитов на новые через refs/replace/ и исправляет ссылки на коммиты прямо в сообщениях. Пустые коммиты вычищаются аккуратно: удаляются только те, что стали пустыми из-за фильтрации, а изначально пустые остаются нетронутыми, если не потеряли родителя. Точно так же обрабатываются вырожденные merge-коммиты — они удаляются, лишь когда становятся топологически бессмысленными и не несут изменений.

Эта работа также подтолкнула серьёзные улучшения fast-export и fast-import в ядре git, начиная с версии 1.6.1.4 и вплоть до современных релизов.

Читать оригинал →