Irgendwas ist ja immer, heute will ich aus einem GIT Repository (>200MB) ein Verzeichnis incl. der History extrahieren.
Mit Hilfe von Tante Google werde ich schnell fündig und lege los.
Repository clonen
git clone https://... repository
Branch umschreiben
git filter-branch --prune-empty --tag-name-filter cat --subdirectory-filter FOLDER-NAME -- --all
Mit dem folgenden Befehl schreiben wir jetzt die „Geschichte“ (History) um. Dabei ist folgendes zu beachten:
--prune-empty
entfernt „leere“ Commits--tag-name-filter cat
aktualisiert ggf. Tags-- --all
als Basis nehme ich den aktuellen Branch, ich will keinen neuen anlegen
Repository aufräumen – Part I
Jetzt haben wir den aktuellen Branch so umgeschrieben, als wenn er schon immer den Inhalt das angegebenem Verzeichnisses hatte. Das Problem ist nur, die Dateien der anderen Branches, Tags usw. sind immer noch im Repository.
In den meisten HowTos im Netz kommen jetzt die folgenden Tipps:
- Alle Branches, die man nicht brauch löschen
- Alle remotes löschen
- Das „reflog“ „expiren“:
git reflog expire --expire=all --all
- Aufräumen:
git gc --aggressive --prune=now
- …
- schlechte Kommentare, wenn es dann doch nicht geht
Alle Tipps haben in meinem Fall viel Zeit gekostet, am Ende konnte ich das Repository nie auf eine vernünftige Größe bekommen.
Repository aufräumen – Part II
Wie häufig reicht es eben nicht aus, mit einem guten Halbwissen plus den Tipps von Tante Google los zu legen.
Als nächstes habe ich mir ein Zeit genommen, um zu verstehen, was git
so alles in seinem Repository speichert und wie. Hier kann ich das Kapitel „Git Internals“ (10.1 – 10.5) empfehlen (Buch ProGit).
Weiterhin war die Doku zu dem Befehl git filter-branch
extrem hilfreich. Im Abschnitt „CHECKLIST FOR SHRINKING A REPOSITORY“ habe ich dann gelesen und verstanden wie man ein Repository shrinken kann.
In meinem Fall hatte git filter-branch
alle „alten“ Branches und Tags als Original in einem intern Folder gespeichert. So wurden alle alten Commits immer noch referenziert und git gc
konnte nix aufräumen.
In meinem Fall habe ich mich für das Clonen entschieden und clone nur den „altuellen“ Branch.
git clone --single-branch --branch develop file:///path/to/repo repositoy-clean
Auch hier war die original Dokumentation wieder extrem hilfreich: Beim Clonen die Quelle immer als URL, also mit dem Prefix file://… angeben — denn sonst macht git
nur Hard-Links und man hat ein gleich großes Repository.
Als nächste habe ich mit den bekannten Mitteln das neue Repository wieder auf den Server geschoben und im alten das Verzeichnis gelöscht.
Zusammenfassung<
- Mit Git kann jeder Folder, incl. seiner History, aus einem Repository extrahiert werden — ohne dass wir den ganzen Rest an Commits behalten müssen.
- Und wieder habe ich etwas gelernt: Ich habe eine Ahnung, wie cool
git
seine interne Datenbank aufbaut und was daraus fürs Aufräumen resultiert. - Tante Google hat zwar viele Tipps parat (die leider in vielen Fällen keine Hintergrundinformationen bieten) — und deswegen will ich in Zukunft häufiger die Original-Dokumentation zu Rate ziehen.
Referenzen
- https://git-scm.com/docs/git-filter-branch
- https://git-scm.com/docs/git-clone
- https://git-scm.com/book/en/v2
- https://help.github.com/articles/splitting-a-subfolder-out-into-a-new-repository