По факту, эта статейка — выжимка из статьи с блога Tinned Software / Experiencing Technology. Моего здесь мало.
Удалить файлы из истории git нужно, когда в репозиторий:
- случайно попали критические данные (напр. логины, пароли, токены доступа);
- что-то тяжёлое было когда-то залито, а теперь не нужно и занимает вес в репозитории;
- и простое удаление с коммитом или реверс-коммиты не подходят.
Так как git призван записывать всю историю манипуляций с файлами, придётся перелопачивать всё дерево изменений — весь индекс. А так как мерж-риквесты, форки, ветки и всё такое базируются на этом индексе, ветки потеряют своих родителей: репозиторий придётся другим пользователям клонировать заново, или сбрасывать свои коммиты. Для сохранения наработок придётся делать rebase.
Короче говоря, операция не без последствий. Долгое время думаем о последствиях и вставляем в терминал с открытым корнем репозитория этот код (в дереве не должно оставаться висячих изменений!):
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch путь/к/файлу/относительно/корня.репозитория' \
--prune-empty --tag-name-filter cat -- --all
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now
git push origin --force --all
git push origin --force --tags
Если нужно удалить несколько файлов, надо повторять первые три строки перед последующими.
Переписанное дерево отправляется только с git push … --force
. Гитлабы и гитхабы по умолчанию блокируют такие опасные операции для защищённых веток — как минимум для мастер-ветки. На время отключить можно:
- В Gitlab: страница вашего репозитория → сбоку вкладка "Настройки" → подвкладка "Репозиторий" → "Защищённые ветки" (на сегодня этот заголовок не переведён и называется "Protected Branches"). Жмём Unprotect, затем пушим, после ставим защиту обратно.
- В Github: "Settings" → сбоку вкладка "Branches" → секция "Branch Protection Rules". Здесь нужно посмотреть, на какие ветки оно влияет. Убираем, пушим, ставим защиту заново.
Переход на новое дерево в других репозиториях
На локальной машине у человека, что склонировал ваш репозиторий, всё равно будет старое дерево. У меня также нередко одни репозитории являются субмодулями других. Всем им нужно сначала запросить информацию о новом дереве, а потом сделать жёсткий сброс к последнему коммиту.
Удобнее и понятнее всего это делать в VSCode с расширением Git Graph (сначала нужно нажать на "Fetch Remotes" в правом верхнем углу, а потом через правую кнопку мыши Reset-нуться на нужный коммит). Консолькой тоже можно:
git fetch origin
git reset --hard origin/master
Для большей секьюрности — и для того, чтобы сжать размер репозитория после этого — автор предлагает почистить индекс этого конкретного репозитория:
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=nowr
Ну, думаю, теперь всё.
Комментарии
Отправить комментарий