Конфиденциальные данные или чрезмерное потребление памяти: есть веские причины изменить историю Git. В этом сообщении блога я объяснил, как удалить файлы из истории Git с помощью BFG . Слабое место BFG — отсутствие поддержки прямых путей , поэтому нельзя специально удалять из истории файлы или папки во вложенных папках. С этим пришло время посмотреть на альтернативные решения.
Помимо официально не рекомендуемой ветки git filter , git-filter-repo — один из инструментов для очистки истории. После непродолжительной установки мы сначала анализируем репозиторий и находим, например, самые большие папки в истории:
git filter-repo --analyze
Хорошо быть в папке .git/filter-repo/analysis
генерируются всевозможные файлы TXT:
directories-all-sizes.txt
extensions-all-sizes.txt
path-all-sizes.txt
- ...
Это стоит файла directories-all-sizes.txt
присмотрись повнимательнее:
=== All directories by reverse size ===
Format: unpacked size, packed size, date deleted, directory name
4624417043 3796607988 <present> <toplevel>
4475940396 3778033787 <present> wp-content
4060236681 3694449320 <present> wp-content/uploads
305163809 70576241 <present> wp-content/plugins
123818107 15442735 <present> wp-includes
...
Часто бывает, что вы давно игнорировали и удаляли из HEAD данные в истории (например, папку медиафайлов WordPress wp-content/uploads/
или случайно нажал node_modules
- или vendor
- связующее).
Обычно рекомендует git-filter-repo
после очистки пушим в новый, пустой репозиторий. Здесь перечислено множество причин, почему это имеет смысл и позволяет избежать многих проблем. Тем не менее, может случиться так, что вы захотите отправить в тот же репозиторий, и это также возможно с помощью нескольких подсказок.
Важно отметить, что основные платформы для размещения кода GitHub а также GitLab рекомендуют разные подходы, некоторые из которых отличаются друг от друга. Например, на GitHub мы удаляем wp-content/uploads/
используя следующие шаги git-filter-repo
из истории:
mkdir tmp-repo
cd tmp-repo
git clone git@github.com:foo/bar.git .
cp .git/config /tmp/config-backup
git filter-repo --invert-paths --path wp-content/uploads/
# option 1: same repo
mv /tmp/config-backup .git/config
git push origin --force --all
# option 2: new repo
git remote add origin git@github.com:foo/bar-new.git
git push origin --force --all
cd ..
rm -rf tmp-repo
Теперь мы также можем проверить размер удаленно (изменение размера через API и в пользовательском интерфейсе может занять до 24 часов). Для этого откройте настройки репозитория (если репозиторий принадлежит организации, необходимо предварительно добавить в организацию собственную учетную запись). Теперь мы видим размер:
Процедура немного отличается на GitLab:
mkdir tmp-repo
cd tmp-repo
# option 1: same repo
# Settings > General > Advanced > Export project > download tar.gz file into tmp-repo
tar xzf 20*.tar.gz
git clone --bare --mirror project.bundle
cd project.git
git filter-repo --invert-paths --path wp-content/uploads/
cp ./filter-repo/commit-map /tmp/commit-map-1
# copying the commit-map has to be done after every single command from git filter-repo
# you need the commit-map files later
git remote remove origin
git remote add origin git@gitlab.com:foo/bar.git
# Settings > Repository > Protected branches/Protected branches >
# enable "Allowed to force push to main/master"
git push origin --force 'refs/heads/*'
git push origin --force 'refs/tags/*'
git push origin --force 'refs/replace/*'
# Settings > Repository > Protected branches/Protected branches >
# disable "Allowed to force push to main/master"
date
# wait 30 minutes (😱)
date
# Settings > Repository > upload /tmp/commit-map-X
# option 2: new repo
git clone git@gitlab.com:foo/bar.git .
git filter-repo --invert-paths --path wp-content/uploads/
git remote add origin git@gitlab.com:foo/bar-new.git
# Settings > Repository > Protected branches/Protected branches >
# enable "Allowed to force push to main/master"
git push origin --force --all
# Settings > Repository > Protected branches/Protected branches >
# disable "Allowed to force push to main/master"
cd ..
rm -rf tmp-repo
После еще одного ожидания ~ 5 минут мы можем уйти Settings > Usage Quotas
посмотреть место для хранения:
После удаления важно, чтобы все вовлеченные разработчики участвовали в последних шагах: если пользователь сейчас выполнит обычную отправку своей собственной локальной копии, это приведет к переносу больших файлов обратно в центральный репозиторий. Поэтому рекомендуются следующие 3 варианта:
- "свежий клон бедняги"
rm -rf .git && git clone xxx temp && mv temp/.git ./.git && rm -rf temp
- Для измененных файлов (в зависимости от приложения):
git checkout -- .
или же.git add -A . && git commit -m "Push obscure file changes." && git push
- "начинать с нуля"
rm -rf repo && git clone xxx .
- "уродливая тяга с перебазированием"
git pull -r
- Здесь у вас все еще есть неочищенная история, но в большинстве случаев вы больше не перезаписываете удаленный репозиторий случайно большим локальным вариантом.
В ходе текущих квот (особенно из-за новых ограничений GitLab ) всегда стоит проверять размер истории ваших репозиториев и подчищать их при необходимости:
GitHub Бесплатно | GitLab Бесплатно | |
Максимальный размер файла | 100 МБ | ∞ |
Максимальный размер репо | 5000 МБ | ∞ |
Максимальный лимит количества репо | ∞ | ∞ |
Максимальный общий размер | ∞ | 5000 МБ |
Наконец, также стоит взглянуть на самостоятельный бесплатный вариант, такой как Гитея бросать. С небольшими усилиями вы можете на очень тонкий сервер самостоятельный экземпляр Git (графический интерфейс на SSL обеспеченный, Резервное копирование включены, контроль над мощный API) host, которые тоже отличные настроить а также лучше с точки зрения защиты данных. Здесь, кстати, тоже можно использовать git-filter-repo
Просто оптимизируйте репозитории:
mkdir tmp-repo
cd tmp-repo
git clone git@git.tld.com:foo/bar.git .
cp .git/config /tmp/config-backup
git filter-repo --invert-paths --path wp-content/uploads/
# option 1: same repo
mv /tmp/config-backup .git/config
git push origin --mirror
# login on the remote command line and run in the repo-folder
sudo -u git git reflog expire --expire=now --all
sudo -u git git gc --aggressive --prune=now
# if you face memory limit issues, modify the git configuration
sudo -u git git config --global pack.windowMemory "100m"
sudo -u git git config --global pack.packSizeLimit "100m"
sudo -u git git config --global pack.threads "1"
# if in web ui the size does not change, make a slight
# modification to a file and push again normally
# option 2: new repo
git remote add origin git@git.tld.com:foo/bar-new.git
git push origin --force --all
cd ..
rm -rf tmp-repo
Вот конкретно команда sudo -u git git gc --aggressive --prune=now
важно (работает cron git gc
в противном случае он слишком длинный сократить время от 2 недель).