К основному контенту

Удалить файлы из истории git, навсегда и бесследно

По факту, эта статейка — выжимка из статьи с блога 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

Ну, думаю, теперь всё.

Комментарии

Популярные сообщения из этого блога

Что делать, если Error mounting: can't read superblock

Вот такая радость меня встретила сегодня утром — дополнительный жёсткий диск в ноутбуке перестал работать. Часть прог не работает, другие не могут найти рабочие проекты. При монтировании диска через тот же Наутилус пишет: Error mounting system-managed device dev/sdb3: can't read superblock on /dev/sdb3 (udisks-error-quark, 0)

Как обновить Fedora, если Error running transaction: package X is already installed

Наконец-то руки дошли обновить федору до версии 33. Только вот нельзя просто так взять её и обновить — ГУИшный установщик ПО найдёт, где выпендриться. Ошибка значит в переводе, что не удаётся провести транзакцию (грубо говоря, установку), из-за того, что такой-то пакет уже установлен. О ужас! Почему это считается вообще ошибкой — философский вопрос, а чинить как-то надо. Запускаем командную строку. Выполняем команды (только прочитайте сначала текст ниже): sudo dnf upgrade --refresh -y sudo dnf update dnf-plugin-system-upgrade -y sudo dnf system-upgrade download --releasever=33 --allowerasing -y -b Первая команда обновляет все пакеты в системе. Вторая обновляет плагин для обновления самой системы. (На самом деле, плагин и так обновится первой командой. Это скорее для проверки существования самого пакета. Если команда валится и пишет, что такого пакета нет, выполните sudo dnf install dnf-plugin-system-upgrade .) Третья скачивает все пакеты, которые нужны для самого обновления

Установить Midnight Commander на Fedora, CentOS и RHEL — файловый менеджер в терминале

Волей-неволей в жизни девопса иногда приходится работать без графического интерфейса. Или же нужно сделать что-то в своей файловой системе без иксов. Midninght Commander — это файловый менеджер с терминальным интерфейсом, который схож визуально с Total Commander с его разделением на два окна. Миднайт командер также поддерживает управлению мышью, да и в общем идеален для тех, кто привык к графическим интерфейсам и боится vim -а (как я). Если ввести dnf search midnight commander , то ничего не найдётся. Всё потому, что в пакетных менеджерах называется он просто mc , а в описании полного названия нет: Устанавливается он довольно просто. Для Fedora: sudo dnf install -y mc Для RHEL/CentOS: sudo yum install -y mc И всё, можно пользоваться: mc