Очистити історію 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 тижні).

Назад