Poufne dane lub zbyt duże zużycie pamięci: istnieją dobre powody, aby chcieć zmienić historię Git. W tym poście na blogu wyjaśniłem, jak usunąć pliki z historii Git przy użyciu BFG . Słabym punktem BFG jest brak obsługi ścieżek bezpośrednich , przez co nie można specjalnie usuwać z historii plików lub folderów w podfolderach. Po tym nadszedł czas, aby przyjrzeć się alternatywnym rozwiązaniom.
Oprócz oficjalnie niezalecanej gałęzi git filter git-filter-repo jest jednym z narzędzi do czyszczenia historii. Po krótkiej instalacji najpierw analizujemy repozytorium i znajdujemy np. największe foldery w historii:
git filter-repo --analyze
Bądź w folderze .git/filter-repo/analysis
wygenerował wszystkie rodzaje plików TXT:
directories-all-sizes.txt
extensions-all-sizes.txt
path-all-sizes.txt
- ...
Warto plik directories-all-sizes.txt
przyjrzyj się bliżej:
=== 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
...
Często zdarza się, że od dawna zignorowałeś i usunąłeś z HEAD dane w historii (na przykład folder multimediów WordPressa) wp-content/uploads/
lub przypadkowo popchnięty node_modules
- lub vendor
-Spoiwo).
Ogólnie poleca git-filter-repo
po oczyszczeniu, wypchnięcie do nowego, pustego repozytorium. Istnieje wiele powodów wymienionych tutaj, dlaczego ma to sens i pozwala uniknąć wielu problemów. Niemniej jednak może się zdarzyć, że chcesz wypchnąć do tego samego repozytorium i jest to również możliwe z kilkoma wskazówkami.
Co ważne, główne platformy hostingowe kodu GitHub oraz GitLab polecam różne podejścia, z których niektóre różnią się od siebie. Na przykład na GitHub usuwamy wp-content/uploads/
wykonując następujące czynności git-filter-repo
z historii:
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
Teraz możemy również sprawdzić rozmiar zdalnie (zmiana rozmiaru przez API i w interfejsie użytkownika może zająć do 24 godzin). Aby to zrobić, otwórz ustawienia repozytorium (jeśli repozytorium należy do organizacji, musisz najpierw dodać własne konto do organizacji). Teraz widzimy rozmiar:
Procedura jest nieco inna na 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
Po kolejnym oczekiwaniu ~5 minut możemy zejść pod Settings > Usage Quotas
zobacz miejsce do przechowywania:
Po usunięciu ważne jest, aby wszyscy zaangażowani programiści byli zaangażowani w ostatnie kroki: jeśli użytkownik wykona teraz normalne push z własną lokalną kopią, spowoduje to migrację dużych plików z powrotem do centralnego repozytorium. Dlatego zalecane są następujące 3 opcje:
- "świeży klon biednego człowieka"
rm -rf .git && git clone xxx temp && mv temp/.git ./.git && rm -rf temp
- Dla zmienionych plików (w zależności od aplikacji):
git checkout -- .
lub.git add -A . && git commit -m "Push obscure file changes." && git push
- "zaczynać od początku"
rm -rf repo && git clone xxx .
- „brzydkie ciągnięcie z rebasem”
git pull -r
- Tutaj nadal masz nieoczyszczoną historię, ale w większości przypadków nie nadpisujesz już przypadkowo zdalnego repozytorium dużym wariantem lokalnym
W trakcie obecnych kwot (szczególnie ze względu na nowe ograniczenia GitLab ) zawsze warto sprawdzić rozmiar historii swoich repozytoriów i w razie potrzeby je wyczyścić:
GitHub za darmo | Bezpłatne GitLab | |
Maksymalny rozmiar pliku | 100MB | ∞ |
Maksymalny limit rozmiaru repo | 5000 MB | ∞ |
Maksymalny limit liczby repo | ∞ | ∞ |
Maksymalny całkowity limit rozmiaru | ∞ | 5000 MB |
Na koniec warto również przyjrzeć się samodzielnemu, darmowemu wariantowi, takiemu jak Gitea rzucić. Przy niewielkim wysiłku możesz na bardzo cienki serwer samoobsługowa instancja Git (GUI per SSL zabezpieczone, Utworzyć kopię zapasową w cenie, kontrola nad potężne API) gospodarz, które również są doskonałe skonfigurować i jest również lepszy pod względem ochrony danych. Tutaj przy okazji możesz również użyć git-filter-repo
Po prostu usprawnij repozytoria:
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
Tutaj konkretnie jest polecenie sudo -u git git gc --aggressive --prune=now
ważne (działający cron git gc
inaczej ma jeden za długi czas suszonych śliwek 2 tygodnie).