Очистити історію Git, частина 2

Конфіденційні дані або надмірне споживання пам’яті: є вагомі причини змінити історію 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 годин). Для цього відкрийте налаштування репозиторію (якщо репозиторій належить організації, ви повинні спочатку додати власний обліковий запис до організації). Тепер бачимо розмір:

GitHub: дисковий простір перед очищенням
GitHub: місце на диску після очищення

У 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 переглянути простір для зберігання:

GitLab: дисковий простір перед очищенням
GitLab: місце на диску після очищення

Після видалення важливо, щоб усі залучені розробники були залучені до останніх кроків: якщо користувач зараз виконає звичайний push із власною локальною копією, це призведе до міграції великих файлів назад до центрального сховища. Тому рекомендовано наступні 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 Мб

Нарешті, також варто поглянути на безкоштовний варіант, який розміщується самостійно Гітея кидати. З невеликими зусиллями ви можете на a дуже тонкий сервер саморозміщений екземпляр Git (GUI per SSL забезпечені, Резервне копіювання включено, контроль над потужний API) хост, які також чудові налаштувати а також кращий з точки зору захисту даних. Тут, до речі, теж можна використовувати 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 тижні).

Назад