Pulisci la cronologia di Git, parte 2

Dati sensibili o consumo eccessivo di memoria: ci sono buone ragioni per voler cambiare la cronologia di Git. In questo post del blog , ho spiegato come eliminare i file dalla cronologia di Git utilizzando BFG . Un punto debole di BFG è la mancanza di supporto per i percorsi diretti , quindi non è possibile rimuovere in modo specifico file o cartelle nelle sottocartelle dalla cronologia. Detto ciò, è tempo di cercare soluzioni alternative.


Oltre al ramo git filter ufficialmente sconsigliato , git-filter-repo è uno degli strumenti per ripulire la cronologia. Dopo una breve installazione , analizziamo prima il repository e troviamo, ad esempio, le cartelle più grandi della storia:

git filter-repo --analyze

Ben essere nella cartella .git/filter-repo/analysis generato tutti i tipi di file TXT:

  • directories-all-sizes.txt
  • extensions-all-sizes.txt
  • path-all-sizes.txt
  • ...

Vale il file directories-all-sizes.txt dai un'occhiata più da vicino:

=== 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
...

Succede spesso di aver ignorato e rimosso a lungo i dati HEAD nella cronologia (ad esempio, la cartella multimediale di WordPress wp-content/uploads/ o uno spinto accidentalmente node_modules- o vendor-Raccoglitore).

Generalmente consiglia git-filter-repo dopo la pulizia, il push in un nuovo repository vuoto. Ci sono numerose ragioni elencate qui, perché questo ha senso ed evita molti problemi. Tuttavia, può succedere di voler eseguire il push sullo stesso repository e ciò è possibile anche con alcuni suggerimenti.

È importante sottolineare che le principali piattaforme di hosting di codice GitHub e GitLab consigliare approcci diversi, alcuni dei quali differiscono tra loro. Ad esempio, su GitHub rimuoviamo wp-content/uploads/ utilizzando i seguenti passaggi git-filter-repo dalla storia:

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

Ora possiamo anche controllare le dimensioni da remoto (la modifica delle dimensioni tramite API e nell'interfaccia utente può richiedere fino a 24 ore). Per fare ciò, apri le impostazioni del repository (se il repository appartiene a un'organizzazione, devi prima aggiungere il tuo account all'organizzazione). Ora vediamo la dimensione:

GitHub: spazio su disco prima della pulizia
GitHub: spazio su disco dopo la pulizia

La procedura è leggermente diversa su 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

Dopo un'altra attesa di circa 5 minuti possiamo andare sotto Settings > Usage Quotas visualizzare lo spazio di archiviazione:

GitLab: spazio su disco prima della pulizia
GitLab: spazio su disco dopo la pulizia

Dopo la rimozione, è importante che tutti gli sviluppatori coinvolti siano coinvolti nei passaggi finali: se un utente ora esegue un normale push con la propria copia locale, ciò comporterebbe la migrazione di file di grandi dimensioni al repository centrale. Pertanto, sono consigliate le seguenti 3 opzioni:

  • "il clone fresco del povero"
    • rm -rf .git && git clone xxx temp && mv temp/.git ./.git && rm -rf temp
    • Per file modificati (a seconda dell'applicazione): git checkout -- . o. git add -A . && git commit -m "Push obscure file changes." && git push
  • "iniziare da zero"
    • rm -rf repo && git clone xxx .
  • "brutto tiro con rebase"
    • git pull -r
    • Qui hai ancora la cronologia non pulita, ma nella maggior parte dei casi non sovrascrivi più accidentalmente il repository remoto con la variante large local

Nel corso delle attuali quote (soprattutto a causa delle nuove restrizioni di GitLab ), vale sempre la pena controllare la dimensione della cronologia dei tuoi repository e ripulirli se necessario:

GitHub gratuitoGitLab gratuito
Limite massimo della dimensione del file100 MB
Limite massimo della dimensione del repository5.000 MB
Limite massimo di conteggio dei repo
Limite massimo di dimensioni complessive5.000 MB

Infine, vale anche la pena dare un'occhiata a una variante gratuita self-hosted come Gitea gettare. Con poco sforzo puoi su a server molto sottile un'istanza Git self-hosted (GUI per SSL protetto, Backup incluso, controllo potente API) host, anch'essi eccellenti configurare ed è anche superiore in termini di protezione dei dati. Qui, tra l'altro, puoi anche usare git-filter-repo Semplifica semplicemente i repository:

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

Ecco in particolare il comando sudo -u git git gc --aggressive --prune=now importante (il cron in esecuzione git gc altrimenti ne ha uno troppo lungo tempo di potatura di 2 settimane).

Indietro