Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як переписати історію всього репозиторію: видалити великий файл чи змінити автора в усіх комітах?

Для змін, які зачіпають усю історію (а не кілька останніх комітів), interactive rebase не підходить. Інструмент для цього - git-filter-repo, який рекомендує сам проєкт Git замість застарілого й повільного git filter-branch.

brew install git-filter-repo     # чи pip install git-filter-repo

Типові задачі:

# видалити файл з усієї історії
git filter-repo --invert-paths --path storage/dump.sql

# видалити всі файли, більші за 10 МБ
git filter-repo --strip-blobs-bigger-than 10M

# лишити лише підкаталог (виділити пакет в окремий репозиторій)
git filter-repo --subdirectory-filter packages/billing

# замінити текст у всіх файлах історії (наприклад, ключ)
git filter-repo --replace-text replacements.txt

Змінити автора - через файл .mailmap:

Olena Petrenko <olena@company.com> <olena@old-laptop.local>
git filter-repo --mailmap .mailmap

Що відбувається: кожен коміт, починаючи з першого зміненого, отримує новий хеш - бо змінюється вміст або батько. Фактично це новий репозиторій зі схожою історією.

Наслідки, які треба спланувати:

  • усі клони застаріли: колеги мають зробити свіжий клон, а не pull - інакше старі коміти повернуться при наступному злитті;
  • force push усіх гілок і тегів, тимчасове зняття захисту гілок;
  • відкриті pull request посилаються на старі коміти - їх доведеться перестворити;
  • посилання на коміти в задачах, документації, changelog стають недійсними;
  • копії на сервері: GitHub ще деякий час зберігає старі об'єкти в кеші й у форках - для повного видалення чутливих даних потрібне звернення в підтримку.

Захисні механізми filter-repo: за замовчуванням він відмовляється працювати не на свіжому клоні (щоб не зіпсувати робочий репозиторій) і видаляє origin після переписування, щоб випадковий push не перезаписав сервер.

Альтернатива для великих файлів - BFG Repo-Cleaner: простіший, але менш гнучкий.

Перед тим як переписувати - перевірити, чи не простіше залишити історію як є: великий файл у минулому лише збільшує розмір клону, а витік секрету лікується ротацією ключа, а не переписуванням історії.

Докладніше в документації: git-filter-repo

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання