Der einfache Weg™
Es stellt sich heraus, dass dies eine so häufige und nützliche Praxis ist, dass es die Oberherren von Git wirklich einfach gemacht haben (hinzugefügt in Version 1.7.11 - Mai 2012). Außerdem gibt es ein praktisches Beispiel in der Anleitung unten.
-
Bereiten Sie das alte Repository vor
cd
git subtree split -P -b
Hinweis: darf keine führenden oder abschließenden Zeichen enthalten. Beispielsweise muss der Ordner mit dem Namen subproject
als subproject
übergeben werden, NICHT als ./subproject/
Hinweis: ist ein Branch, den Sie im bestehenden/alten Repo erstellen, NICHT den neuen [der später kommt].
Hinweis für Windows-Benutzer: Wenn Ihre Ordnerstruktur größer als 1 ist, muss den *nix-Stil-Ordnerseparator (/) enthalten. Beispielsweise muss der Ordner mit dem Namen path1\path2\subproject
als path1/path2/subproject
übergeben werden.
-
Erstellen Sie das neue Repository
mkdir ~/ && cd ~/
git init
git pull
-
Verknüpfen Sie das neue Repository mit GitHub oder wo auch immer
git remote add origin
git push -u origin master
-
Bereinigen Sie im falls gewünscht
git rm -rf
Hinweis: Dies hinterlässt alle historischen Verweise im Repository. Siehe den Anhang unten, wenn Sie tatsächlich besorgt sind, dass ein Passwort committed wurde oder wenn Sie die Dateigröße Ihres .git
-Ordners verringern müssen.
Beispiel
Das sind die gleichen Schritte wie oben, aber nach meinen genauen Schritten für mein Repository anstatt zu verwenden.
Hier ist ein Projekt, das ich für die Implementierung von JavaScript-Browsermodulen in Node habe:
tree ~/node-browser-compat
node-browser-compat
ArrayBuffer
Audio
Blob
FormData
atob
btoa
location
navigator
Ich möchte einen einzelnen Ordner, btoa
, in ein separates Git-Repository auslagern
cd ~/node-browser-compat/
git subtree split -P btoa -b btoa-only
Jetzt habe ich einen neuen Branch, btoa-only
, der nur Commits für btoa
hat, und ich möchte ein neues Repository erstellen.
mkdir ~/btoa/ && cd ~/btoa/
git init
git pull ~/node-browser-compat btoa-only
Dann erstelle ich ein neues Repo auf GitHub oder Bitbucket oder wo auch immer und füge es als origin
hinzu
git remote add origin git@github.com:node-browser-compat/btoa.git
git push -u origin master
Schöner Tag!
Hinweis: Wenn Sie ein Repo mit einem README.md
, .gitignore
und LICENSE
erstellt haben, müssen Sie zuerst pullen:
git pull origin master
git push origin master
Zuletzt möchte ich den Ordner aus dem größeren Repo entfernen
git rm -rf btoa
Bereinigung Ihres Verlaufs
Standardmäßig werden Dateien aus Git entfernen, entfernt sie tatsächlich nicht; es bestätigt nur, dass sie nicht mehr da sind. Wenn Sie die historischen Verweise tatsächlich entfernen möchten (d. h. Sie haben ein Passwort committed), müssen Sie dies tun:
git filter-branch --prune-empty --tree-filter 'rm -rf ' HEAD
Danach können Sie überprüfen, dass Ihre Datei oder Ihr Ordner gar nicht mehr im Git-Verlauf auftaucht:
git log -- # sollte nichts anzeigen
Allerdings können Sie Löschungen nicht "pushen" zu GitHub und ähnlichen. Wenn Sie es versuchen, erhalten Sie einen Fehler und müssen git pull
ausführen, bevor Sie git push
können - und dann haben Sie wieder alles in Ihrem Verlauf.
Wenn Sie also den Verlauf vom "Ursprung" löschen wollen - also um ihn von GitHub, Bitbucket usw. zu löschen - müssen Sie das Repo löschen und eine bereinigte Kopie des Repos erneut pushen. Aber warten Sie - es gibt mehr! - wenn Sie wirklich besorgt sind, ein Passwort oder ähnliches loszuwerden, müssen Sie das Backup bereinigen (siehe unten).
Die Größe von .git
reduzieren
Der zuvor genannte Befehl zum Löschen des Verlaufs hinterlässt immer eine Menge Backup-Dateien - weil Git allzu gerne dabei hilft, Ihr Repo nicht aus Versehen zu ruinieren. Es wird im Laufe der Tage und Monate verwaiste Dateien löschen, aber es lässt sie eine Weile dort, falls Sie merken, dass Sie etwas versehentlich gelöscht haben, was Sie nicht wollten.
Wenn Sie also wirklich den Papierkorb leeren wollen, um die Klonegröße eines Repos sofort zu reduzieren, müssen Sie all diese wirklich seltsamen Dinge tun:
rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune=now
git reflog expire --all --expire-unreachable=0
git repack -A -d
git prune
Trotzdem würde ich empfehlen, diese Schritte nur dann auszuführen, wenn Sie wissen, dass Sie es müssen - nur für den Fall, dass Sie das falsche Unterverzeichnis bereinigt haben, wissen Sie? Die Backup-Dateien sollten nicht geklont werden, wenn Sie das Repo pushen; sie werden einfach in Ihrer lokalen Kopie sein.
Quelle
10 Stimmen
Das ist jetzt trivial mit
git filter-branch
siehe meine Antwort unten.16 Stimmen
@jeremyjjbrown hat recht. Es ist zwar nicht mehr schwierig dies zu tun, aber es ist schwierig, die richtige Antwort auf Google zu finden, da die alten Antworten die Ergebnisse dominieren.
4 Stimmen
Die Verwendung von
git filter-branch
wird abgeraten. Siehe Warnung in der Dokumentation.3 Stimmen
Bitte verwenden Sie ein alternatives History-Filter-Tool wie git filter-repo.