Come rimuovere gli oggetti inutilizzati da un repository git?


89

Ho accidentalmente aggiunto, eseguito il commit e inviato un enorme file binario con il mio ultimo commit a un repository Git.

Come posso fare in modo che Git rimuova gli oggetti che sono stati creati per quel commit in modo che la mia .gitdirectory si riduca di nuovo a una dimensione sana?

Modifica : grazie per le tue risposte; Ho provato diverse soluzioni. Nessuno ha funzionato. Ad esempio quello di GitHub ha rimosso i file dalla cronologia, ma la .gitdimensione della directory non è diminuita:

$ BADFILES=$(find test_data -type f -exec echo -n "'{}' " \;)

$ git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $BADFILES" HEAD
Rewrite 14ed3f41474f0a2f624a440e5a106c2768edb67b (66/66)
rm 'test_data/images/001.jpg'
[...snip...]
rm 'test_data/images/281.jpg'
Ref 'refs/heads/master' was rewritten

$ git log -p # looks nice

$ rm -rf .git/refs/original/
$ git reflog expire --all
$ git gc --aggressive --prune
Counting objects: 625, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (598/598), done.
Writing objects: 100% (625/625), done.
Total 625 (delta 351), reused 0 (delta 0)

$ du -hs .git
174M    .git
$ # still 175 MB :-(

13
Solo un promemoria per i moderatori, questa domanda appartiene al 100% a SO, non a superutente.
VonC


Come accennato qui ( stackoverflow.com/questions/685319/… ), hai provato un repack dopo il tuo gc? git-repack -aseguito da git-prune-packedper esempio. Vedi blog.felipebalbi.com/2007/12/19/…
VonC

2
@ Jonas: e se, dopo aver fatto tutto questo, clonassi il tuo repo? Otterresti quindi un clone con la dimensione ridotta desiderata?
VonC

1
@Jonas: dopo tutto quello che hai fatto ( filter-branch, gc, repack, ...), no, non si dovrebbe vedere alcun male commesso a tutti. Questo è un segno che la pulizia non è avvenuta come previsto.
VonC

Risposte:


127

Ho risposto altrove e copierò qui poiché ne sono orgoglioso!

... e senza ulteriori indugi, posso presentarti questo utile script, git-gc-all, garantito per rimuovere tutta la tua spazzatura git fino a quando potrebbero venire con variabili di configurazione extra:

git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 \
  -c gc.rerereresolved=0 -c gc.rerereunresolved=0 \
  -c gc.pruneExpire=now gc "$@"

L'opzione --aggressive potrebbe essere utile.

NOTA: questo rimuoverà TUTTE le cose non referenziate, quindi non venire a piangere da me se decidi in seguito di volerne tenere alcune!

Potrebbe anche essere necessario eseguire prima qualcosa di simile, oh caro, git è complicato !!

git remote rm origin
rm -rf .git/refs/original/ .git/refs/remotes/ .git/*_HEAD .git/logs/
git for-each-ref --format="%(refname)" refs/original/ |
  xargs -n1 --no-run-if-empty git update-ref -d

Ho messo tutto questo in uno script, qui:

http://sam.nipl.net/b/git-gc-all-ferocious


Come in stackoverflow.com/questions/1904860/… , +1 a te di nuovo.
VonC

18
eccellente: D il mio piano malvagio per ottenere più punti clonando le risposte ha funzionato !! 1;)
Sam Watkins

Sì! Ha funzionato, ma ho dovuto eseguire lo script completo. L'esecuzione del solo comando gc (con le opzioni di configurazione) non era sufficiente.
Daniel

4
102m a 160k .. efficace e distruttivo
prusswan

4
Grazie mille per la sceneggiatura! Informazioni bonus: il xargscomando produce un errore su OS X a causa di un'opzione non riconosciuta. Soluzione più semplice: installa GNU xargs tramite homebrew brew install findutilse sostituisci xargscon gxargs.
qqilihq

26

Il tuo git reflog expire --allnon è corretto. Rimuove le voci di reflog che sono più vecchie del tempo di scadenza, che per impostazione predefinita è di 90 giorni. Usa git reflog expire --all --expire=now.

La mia risposta a una domanda simile affronta il problema dell'eliminazione degli oggetti inutilizzati da un repository.


18

1) Rimuovi il file dal repository git (e non dal filesystem):

  • git rm --cached path/to/file

2) Riduci il repo usando:

  • git gc,

  • o git gc --aggressive

  • o git prune

o una combinazione di quanto sopra come suggerito in questa domanda: Riduci la dimensione del repository git


10

Questa guida sulla rimozione dei dati sensibili può essere applicata, utilizzando lo stesso metodo. Riscrivi la cronologia per rimuovere quel file da ogni revisione in cui era presente. Ciò è distruttivo e causerà conflitti di repository con qualsiasi altro checkout, quindi avvisa prima i collaboratori.

Se vuoi mantenere il file binario disponibile nel repo per altre persone, non c'è un modo reale per fare quello che vuoi. È praticamente tutto o nessuno.


8

La chiave per me si è rivelata essere in esecuzione git repack -A -d -fe quindi git gcridurre le dimensioni del singolo pacchetto git che avevo.


6

Hy!

Git riceve solo gli oggetti di cui ha effettivamente bisogno durante la clonazione dei repository (se lo capisco correttamente)

Quindi puoi modificare l'ultimo commit rimuovendo il file aggiunto per errore, quindi inviare le modifiche al repository remoto (con l'opzione -f per sovrascrivere anche il vecchio commit sul server)

Quindi, quando crei un nuovo clone di quel repository, la sua directory .git dovrebbe essere piccola come prima del commit dei file grandi.

Facoltativamente, se desideri rimuovere anche i file non necessari dal server, puoi eliminare il repository sul server e inviare la tua copia appena clonata (che ha la cronologia completa)



4
git filter-branch --index-filter 'git rm --cached --ignore-unmatch Filename' --prune-empty -- --all

Ricorda di cambiare Filenameper quello che vuoi rimuovere dal repository.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.