Wie entferne ich nicht verwendete Objekte aus einem Git-Repository?


87

Ich habe versehentlich eine riesige Binärdatei hinzugefügt, festgeschrieben und mit meinem neuesten Commit in ein Git-Repository verschoben.

Wie kann ich Git veranlassen, die Objekte zu entfernen, die für dieses Commit erstellt wurden / wurden, damit mein .gitVerzeichnis wieder auf eine normale Größe verkleinert wird?

Edit : Danke für deine Antworten; Ich habe verschiedene Lösungen ausprobiert. Keiner hat funktioniert. Zum Beispiel hat der von GitHub die Dateien aus dem Verlauf entfernt, aber die .gitVerzeichnisgröße hat sich nicht verringert:

$ 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
Nur eine Erinnerung für Moderatoren, diese Frage gehört zu 100% zu SO, nicht zu Superuser.
VonC


Wie hier erwähnt ( stackoverflow.com/questions/685319/… ), haben Sie nach Ihrem GC ein Umpacken versucht? git-repack -agefolgt von git-prune-packedzum Beispiel. Siehe blog.felipebalbi.com/2007/12/19/…
VonC

2
@ Jonas: Und was ist, wenn Sie nach all dem Ihr Repo klonen? Würden Sie dann einen Klon mit der gewünschten reduzierten Größe erhalten?
VonC

1
@Jonas: nach allem , was du getan hast ( filter-branch, gc, repack, ...), nein, Sie sollten nicht schlecht sehen überhaupt begehen. Dies ist ein Zeichen dafür, dass die Reinigung nicht wie erwartet stattgefunden hat.
VonC

Antworten:


126

Ich habe dies an anderer Stelle beantwortet und werde es hier kopieren, da ich stolz darauf bin!

... und ohne weiteres darf ich Ihnen dieses nützliche Skript vorstellen, git-gc-all, das garantiert Ihren gesamten Git-Müll entfernt, bis zusätzliche Konfigurationsvariablen verfügbar sind:

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

Die Option --aggressive kann hilfreich sein.

HINWEIS: Dadurch werden ALLE nicht referenzierten Objekte entfernt. Weinen Sie also nicht zu mir, wenn Sie später entscheiden, dass Sie einige davon behalten möchten!

Möglicherweise müssen Sie auch zuerst so etwas ausführen, oh je, git ist kompliziert !!

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

Ich habe das alles hier in ein Skript geschrieben:

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


Wie in stackoverflow.com/questions/1904860/… , wieder +1 an Sie.
VonC

18
ausgezeichnet: D mein böser Plan, mehr Punkte durch Klonen von Antworten zu bekommen, hat funktioniert !! 1;)
Sam Watkins

Ja! Das hat funktioniert, aber ich musste das vollständige Skript ausführen. Es reichte nicht aus, nur den Befehl gc (mit Konfigurationsoptionen) auszuführen.
Daniel

4
102m bis 160k .. effektiv und zerstörerisch
prusswan

4
Vielen Dank für das Skript! Bonusinfo: Der xargsBefehl erzeugt unter OS X einen Fehler aufgrund einer nicht erkannten Option. Einfachste Lösung: Installieren Sie GNU xargs über Homebrew brew install findutilsund ersetzen Sie es xargsdurch gxargs.
Qqilihq

26

Dein git reflog expire --allist falsch. Es werden Reflog-Einträge entfernt, die älter als die Ablaufzeit sind, die standardmäßig 90 Tage beträgt. Verwenden Sie git reflog expire --all --expire=now.

Meine Antwort auf eine ähnliche Frage befasst sich mit dem Problem, nicht verwendete Objekte wirklich aus einem Repository zu entfernen.


18

1) Entfernen Sie die Datei aus dem Git-Repo (und nicht aus dem Dateisystem):

  • git rm --cached path/to/file

2) Verkleinern Sie das Repo mit:

  • git gc,

  • oder git gc --aggressive

  • oder git prune

oder eine Kombination der oben genannten, wie in dieser Frage vorgeschlagen: Reduzieren Sie die Größe des Git-Repositorys


10

Diese Anleitung zum Entfernen vertraulicher Daten kann mit derselben Methode angewendet werden. Sie schreiben den Verlauf neu, um diese Datei aus jeder Revision zu entfernen, in der sie vorhanden war. Dies ist destruktiv und führt zu Repo-Konflikten mit anderen Checkouts. Warnen Sie daher zuerst alle Mitarbeiter.

Wenn Sie die Binärdatei im Repo für andere Personen verfügbar halten möchten, gibt es keine echte Möglichkeit, das zu tun, was Sie möchten. Es ist so ziemlich alles oder nichts.


8

Es stellte sich heraus, dass der Schlüssel für mich lief git repack -A -d -fund dann git gcdie Größe des einzelnen Git-Packs reduzierte, den ich hatte.


6

Hy!

Git empfängt nur Objekte, die es beim Klonen von Repositorys tatsächlich benötigt (wenn ich es richtig verstehe)

Sie können also das letzte Commit ändern, indem Sie die versehentlich hinzugefügte Datei entfernen und Ihre Änderungen dann in das Remote-Repository übertragen (mit der Option -f, um das alte Commit auch auf dem Server zu überschreiben).

Wenn Sie dann einen neuen Klon dieses Repos erstellen, sollte das .git-Verzeichnis so klein sein wie vor dem Festschreiben der großen Datei (en).

Wenn Sie auch die unnötigen Dateien vom Server entfernen möchten, können Sie optional das Repository auf dem Server löschen und Ihre neu geklonte Kopie (mit dem vollständigen Verlauf) verschieben.



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

Denken FilenameSie daran, diejenige zu ändern, die Sie aus dem Repository entfernen möchten.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.