Git: come rimuovere il file dal commit storico?


113

Ho un commit con ID 56f06019 (ad esempio). In quel commit ho inserito accidentalmente file di grandi dimensioni (50 MB). In un altro commit aggiungo lo stesso file ma nella giusta dimensione (piccolo). Ora il mio repository quando clone è troppo pesante :( Come rimuovere quel file di grandi dimensioni dalla cronologia del repository per ridurre le dimensioni del mio repository?


nel mio caso, non è un file di grandi dimensioni, ma un file di configurazione contenente i crediti del database. Studiavo git, a quel tempo non ero a conoscenza di .gitignore.
Rashi


Risposte:


165

Il capitolo 9 del libro Pro Git ha una sezione sulla rimozione di oggetti .

Consentitemi di delineare brevemente i passaggi qui:

git filter-branch --index-filter \
    'git rm --cached --ignore-unmatch path/to/mylarge_50mb_file' \
    --tag-name-filter cat -- --all

Come l'opzione di ribasatura descritta prima, filter-branchè l'operazione di riscrittura. Se hai pubblicato la cronologia, dovrai --forcespingere i nuovi ref.

L' filter-branchapproccio è notevolmente più potente rebasedell'approccio, dal momento che

  • ti permette di lavorare su tutti i branch / ref contemporaneamente,
  • rinomina qualsiasi tag al volo
  • funziona in modo pulito anche se ci sono stati diversi commit di unione dall'aggiunta del file
  • funziona in modo pulito anche se il file è stato (ri) aggiunto / rimosso più volte nella storia di (un) ramo (i)
  • non crea nuovi commit non correlati, ma piuttosto li copia modificando gli alberi ad essi associati. Ciò significa che cose come commit firmati, note di commit ecc. Vengono conservate

filter-branch mantiene anche i backup, quindi la dimensione del repository non diminuirà immediatamente a meno che non scadano i reflog e la raccolta dei rifiuti:

rm -Rf .git/refs/original       # careful
git gc --aggressive --prune=now # danger

1
Vale la pena notare che questo non sembra funzionare con Windows cmd.exe. Sembra funzionare bene con Cygwin, però.
Nome falso

2
Ho ottenuto il ramo di filtro git sopra per funzionare utilizzando virgolette doppie anziché virgolette singole (su Windows Server 2012 cmd.exe)
JCii

1
Ciò che ha funzionato per me è stata questa riga di comando del ramo di filtro. git filter-branch --force --index-filter 'git rm --ignore-unmatch --cached PathTo/MyFile/ToRemove.dll' -- fbf28b005^.. Allora rm --recursive --force .git/refs/originale rm --recursive --force .git/logs poi ho usato il git prune --expire now e git gc --aggressive Questo ha funzionato meglio per me rispetto ai tuoi passaggi esatti elencati sopra. Grazie per aver incluso il link al libro Git Pro perché è stato inestimabile.
dacke.geo

Dopo che il comando di filtro-ramo, l'unico modo ho potuto ottenere la dimensione della cartella in giù .git era di seguire il comando trovato qui: stackoverflow.com/questions/1904860/... git -c gc.reflogExpire = 0 -c gc. reflogExpireUnreachable = 0 -c gc.rerereresolved = 0 \ -c gc.rerereunresolved = 0 -c gc.pruneExpire = ora gc "$ @"
Steve Ardis

Per ridurre il repository, ho usato i comandi elencati in git filter-branch doc: git-scm.com/docs/…
Ludovic Ronsin


0

Avrai bisogno di git rebase in modalità interattiva vedi un esempio qui: Come posso rimuovere un commit su GitHub? e come rimuovere vecchi commit .

Se il tuo commit è a HEAD meno 10 commit:

$ git rebase -i HEAD~10

Dopo l'edizione della cronologia, è necessario eseguire il push della "nuova" cronologia, è necessario aggiungere il +to force (vedere refspec nelle opzioni push ):

$ git push origin +master

Se altre persone hanno già clonato il tuo repository, dovrai informarle, perché hai appena cambiato la cronologia.


3
Ciò non rimuove il file di grandi dimensioni dalla cronologia. Inoltre, il modo canonico per forzare il push è git push --forceo git push -f(che non richiede che le persone conoscano il target push del ramo)
vedi il

Sulla base della domanda, il nuovo file è esattamente lo stesso del vecchio file, cioè lo stesso percorso. Questo è il motivo per cui non è possibile utilizzare direttamente git rmsul percorso.
Loïc d'Anterroches

2
@sehe, se esegui un rebase eliminando il commit con il file enorme, è andato per sempre.
vonbrand

@vonbrand solo da quel ramo che hai ribasato. Non presumo che il ramo "da" venga eliminato. Ma sì, se elimini un ramo dell'albero delle revisioni, ciò aiuterà: _
vedi il

@sehe, certo, devi inseguire tutti i rami contenenti il ​​commit incriminato. Se è prima di un po 'di follia nel repo, dovrai riorganizzare molto. Ma rebase è lo strumento per questo.
vonbrand

0

Ho provato a utilizzare la seguente risposta su Windows https://stackoverflow.com/a/8741530/8461756

Le virgolette singole non funzionano su Windows, servono le virgolette doppie.

Seguire ha funzionato per me.

git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PathRelativeRepositoryRoot / bigfile.csv" - --all

Dopo aver rimosso il file di grandi dimensioni, sono stato in grado di inviare le mie modifiche a GitHub Master.


0

Puoi usare un semplice comando per eliminare

 git rm -r -f app/unused.txt 
 git rm -r -f yourfilepath
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.