Ich habe ein Git- Repository, das eine Reihe von Unterverzeichnissen enthält. Jetzt habe ich festgestellt, dass eines der Unterverzeichnisse nicht mit dem anderen verwandt ist und in ein separates Repository getrennt werden sollte.
Wie kann ich dies tun, während der Verlauf der Dateien im Unterverzeichnis gespeichert wird?
Ich denke, ich könnte einen Klon erstellen und die unerwünschten Teile jedes Klons entfernen, aber ich nehme an, dies würde mir beim Auschecken einer älteren Revision usw. den vollständigen Baum geben. Dies könnte akzeptabel sein, aber ich würde es vorziehen, so tun zu können, als ob der Zwei Repositorys haben keinen gemeinsamen Verlauf.
Um es klar zu machen, habe ich die folgende Struktur:
XYZ/
.git/
XY1/
ABC/
XY2/
Aber ich möchte stattdessen Folgendes:
XYZ/
.git/
XY1/
XY2/
ABC/
.git/
ABC/
git filter-branch
siehe meine Antwort unten.Antworten:
Update : Dieser Prozess ist so häufig, dass das Git-Team ihn mit einem neuen Tool viel einfacher gemacht hat
git subtree
. Siehe hier: Unterverzeichnis (Verschieben) in ein separates Git-Repository trennenSie möchten Ihr Repository klonen und dann
git filter-branch
alles außer dem Unterverzeichnis markieren, das in Ihrem neuen Repo durch Müll gesammelt werden soll.So klonen Sie Ihr lokales Repository:
(Hinweis: Das Repository wird mithilfe von Hardlinks geklont. Dies ist jedoch kein Problem, da die fest verknüpften Dateien nicht selbst geändert werden - neue werden erstellt.)
Lassen Sie uns nun die interessanten Zweige beibehalten, die wir ebenfalls neu schreiben möchten, und dann den Ursprung entfernen, um ein Verschieben zu vermeiden und sicherzustellen, dass alte Commits nicht vom Ursprung referenziert werden:
oder für alle entfernten Filialen:
Jetzt möchten Sie möglicherweise auch Tags entfernen, die keine Beziehung zum Teilprojekt haben. Sie können dies auch später tun, müssen Ihr Repo jedoch möglicherweise erneut beschneiden. Ich habe dies nicht getan und ein
WARNING: Ref 'refs/tags/v0.1' is unchanged
für alle Tags erhalten (da sie alle nichts mit dem Teilprojekt zu tun hatten ). Darüber hinaus wird nach dem Entfernen solcher Tags mehr Speicherplatz zurückgefordert. Anscheinendgit filter-branch
sollte es möglich sein, andere Tags umzuschreiben, aber ich konnte dies nicht überprüfen. Wenn Sie alle Tags entfernen möchten, verwenden Siegit tag -l | xargs git tag -d
.Verwenden Sie dann Filter-Branch und Reset, um die anderen Dateien auszuschließen, damit sie bereinigt werden können. Fügen wir außerdem hinzu
--tag-name-filter cat --prune-empty
, um leere Commits zu entfernen und Tags neu zu schreiben (beachten Sie, dass hierdurch die Signatur entfernt werden muss):oder alternativ, um nur den HEAD-Zweig neu zu schreiben und Tags und andere Zweige zu ignorieren:
Löschen Sie dann die Backup-Reflogs, damit der Speicherplatz wirklich wiederhergestellt werden kann (obwohl der Vorgang jetzt destruktiv ist).
und jetzt haben Sie ein lokales Git-Repository des ABC-Unterverzeichnisses, dessen gesamter Verlauf erhalten bleibt.
Hinweis: Für die meisten Anwendungen
git filter-branch
sollte tatsächlich der hinzugefügte Parameter vorhanden sein-- --all
. Ja das ist wirklich so --space--all
. Dies müssen die letzten Parameter für den Befehl sein. Wie Matli herausfand, bleiben die Projektzweige und -tags im neuen Repo enthalten.Bearbeiten: Verschiedene Vorschläge aus den Kommentaren unten wurden aufgenommen, um beispielsweise sicherzustellen, dass das Repository tatsächlich verkleinert wird (was vorher nicht immer der Fall war).
quelle
--no-hardlinks
? Das Entfernen eines Hardlinks wirkt sich nicht auf die andere Datei aus. Git-Objekte sind ebenfalls unveränderlich. Nur wenn Sie die Eigentümer- / Dateiberechtigungen ändern möchten, die Sie benötigen--no-hardlinks
.filter-branch
ist--prune-empty
das Entfernen jetzt leerer Commits.-- --all
. Ich liefgit remote rm origin
auch undgit tag -l | xargs git tag -d
vor demgit filter-branch
Befehl. Dadurch wurde mein.git
Verzeichnis von 60 Millionen auf ~ 300 KB verkleinert . Beachten Sie, dass ich beide Befehle ausführen musste, um die Größenreduzierung zu erhalten.Der einfache Weg ™
Es stellt sich heraus, dass dies eine so verbreitete und nützliche Praxis ist, dass die Overlords von Git es wirklich einfach gemacht haben, aber Sie müssen eine neuere Version von Git haben (> = 1.7.11 Mai 2012). Im Anhang erfahren Sie, wie Sie das neueste Git installieren. Außerdem finden Sie in der folgenden exemplarischen Vorgehensweise ein Beispiel aus der Praxis .
Bereiten Sie das alte Repo vor
Hinweis:
<name-of-folder>
darf KEINE führenden oder nachfolgenden Zeichen enthalten. Beispielsweise muss der Ordner mit dem Namensubproject
MUSS alssubproject
NICHT übergeben werden./subproject/
Hinweis für Windows-Benutzer: Wenn Ihre Ordnertiefe> 1 ist,
<name-of-folder>
muss ein Ordnertrennzeichen (/) im * nix-Stil vorhanden sein. Beispielsweise muss der Ordner mit dem Namenpath1\path2\subproject
MUSS als übergeben werdenpath1/path2/subproject
Erstellen Sie das neue Repo
Verknüpfe das neue Repo mit GitHub oder wo auch immer
Aufräumen innen
<big-repo>
, wenn gewünschtHinweis : Dadurch bleiben alle historischen Referenzen im Repository Lesen Sie Anhang, wenn Sie tatsächlich Bedenken haben, ein Kennwort festgeschrieben zu haben, oder wenn Sie die Dateigröße Ihres
.git
Ordners verringern müssen ....
Exemplarische Vorgehensweise
Dies sind die gleichen Schritte wie oben , aber befolgen Sie meine genauen Schritte für mein Repository, anstatt sie zu verwenden
<meta-named-things>
.Hier ist ein Projekt zur Implementierung von JavaScript-Browsermodulen in Node:
Ich möchte einen einzelnen Ordner
btoa
in ein separates Git-Repository aufteilenIch habe jetzt einen neuen Zweig, für den
btoa-only
nur Commits vorhanden sind,btoa
und ich möchte ein neues Repository erstellen.Als nächstes erstelle ich ein neues Repo auf GitHub oder Bitbucket oder was auch immer und füge es als das hinzu
origin
Glücklicher Tag!
Hinweis: Wenn Sie ein Repo mit einem erstellt
README.md
,.gitignore
undLICENSE
, müssen Sie zuerst ziehen:Zuletzt möchte ich den Ordner aus dem größeren Repo entfernen
...
Blinddarm
Neueste Git unter macOS
So erhalten Sie die neueste Version von Git mit Homebrew :
Neueste Git auf Ubuntu
Wenn das nicht funktioniert (Sie haben eine sehr alte Version von Ubuntu), versuchen Sie es
Wenn das immer noch nicht funktioniert, versuchen Sie es
Danke an rui.araujo aus den Kommentaren.
Löschen Sie Ihre Geschichte
Durch das Entfernen von Dateien aus Git werden diese standardmäßig nicht entfernt, sondern nur festgeschrieben, dass sie nicht mehr vorhanden sind. Wenn Sie die historischen Referenzen tatsächlich entfernen möchten (dh Sie haben ein Kennwort festgeschrieben), müssen Sie Folgendes tun:
Danach können Sie überprüfen, ob Ihre Datei oder Ihr Ordner überhaupt nicht mehr im Git-Verlauf angezeigt wird
Sie können jedoch keine Löschvorgänge auf GitHub und dergleichen "pushen" . Wenn Sie es versuchen, erhalten Sie eine Fehlermeldung und müssen dies tun,
git pull
bevor Sie könnengit push
tun - und dann haben Sie wieder alles in Ihrer Geschichte.Wenn Sie also den Verlauf aus dem "Ursprung" löschen möchten, dh aus GitHub, Bitbucket usw. löschen möchten, müssen Sie das Repo löschen und eine beschnittene Kopie des Repos erneut senden. Aber warte - es gibt noch mehr ! - Wenn Sie wirklich Bedenken haben, ein Passwort oder ähnliches loszuwerden, müssen Sie das Backup beschneiden (siehe unten).
Herstellung
.git
kleinerDer oben erwähnte Befehl zum Löschen des Verlaufs hinterlässt immer noch eine Reihe von Sicherungsdateien - weil Git Ihnen nur allzu freundlich hilft, Ihr Repo nicht versehentlich zu ruinieren. Im Laufe der Tage und Monate werden verwaiste Dateien gelöscht, aber sie bleiben für eine Weile dort, falls Sie feststellen, dass Sie versehentlich etwas gelöscht haben, das Sie nicht wollten.
Wenn Sie also den Papierkorb wirklich leeren möchten, um die Klongröße eines Repos sofort zu verringern , müssen Sie all diese wirklich seltsamen Dinge tun:
Trotzdem würde ich empfehlen, diese Schritte nur auszuführen, wenn Sie wissen, dass Sie dies tun müssen - nur für den Fall, dass Sie das falsche Unterverzeichnis beschnitten haben, wissen Sie? Die Sicherungsdateien sollten nicht geklont werden, wenn Sie das Repo pushen. Sie befinden sich nur in Ihrer lokalen Kopie.
Anerkennung
quelle
git subtree
ist immer noch Teil des Ordners 'Contrib' und wird nicht standardmäßig in allen Distributionen installiert. github.com/git/git/blob/master/contrib/subtreepopd
undpushd
macht dies ziemlich implizit und schwieriger zu verstehen, was es zu tun beabsichtigt ...Pauls Antwort erstellt ein neues Repository, das / ABC enthält, entfernt jedoch / ABC nicht aus / XYZ. Der folgende Befehl entfernt / ABC aus / XYZ:
Testen Sie es natürlich zuerst in einem 'clone --no-hardlinks'-Repository und folgen Sie ihm mit den von Paul aufgelisteten Befehlen reset, gc und prune.
quelle
git filter-branch --index-filter "git rm -r -f --cached --ignore-unmatch ABC" --prune-empty HEAD
und es wird viel schneller sein. Der Indexfilter arbeitet mit dem Index, während der Baumfilter für jedes Commit alles auschecken und bereitstellen muss .--index-filter
Methode ausführen, möchten Sie dies möglicherweise auch tungit rm -q -r -f
, damit bei jedem Aufruf nicht für jede gelöschte Datei eine Zeile gedruckt wird.Ich habe festgestellt, dass Sie nach dem
filter-branch
Schritt etwas mehr Arbeit leisten müssen, um den alten Verlauf ordnungsgemäß aus dem neuen Repository zu löschen .Machen Sie den Klon und den Filter:
Entfernen Sie jeden Verweis auf die alte Geschichte. "Origin" verfolgte Ihren Klon und "original" ist der Ort, an dem Filter-Branch das alte Zeug speichert:
Selbst jetzt steckt Ihr Verlauf möglicherweise in einer Packdatei, die fsck nicht berührt. Zerreißen Sie es in Stücke, erstellen Sie eine neue Packdatei und löschen Sie die nicht verwendeten Objekte:
Eine Erklärung hierzu finden Sie im Handbuch für Filterzweige .
quelle
git gc --aggressive --prune=now
fehlt noch, nicht wahr?git gc --aggressive --prune=now
viel neues Repo reduziertBearbeiten: Bash-Skript hinzugefügt.
Die hier gegebenen Antworten haben nur teilweise für mich funktioniert; Viele große Dateien blieben im Cache. Was hat endlich funktioniert (nach Stunden in #git auf freenode):
Bei den vorherigen Lösungen betrug die Repository-Größe etwa 100 MB. Dieser brachte es auf 1,7 MB. Vielleicht hilft es jemandem :)
Das folgende Bash-Skript automatisiert die Aufgabe:
quelle
Dies ist nicht mehr so komplex. Sie können einfach den Befehl git filter-branch für einen Klon Ihres Repos verwenden, um die nicht gewünschten Unterverzeichnisse auszusortieren und dann auf die neue Fernbedienung zu übertragen.
quelle
The result will contain that directory (and only that) as its project root.
tatsächlich der Fall ist, dh die ursprüngliche Projektstruktur bleibt nicht erhalten.Update : Das Git-Teilbaum-Modul war so nützlich, dass das Git-Team es in den Kern gezogen und erstellt hat
git subtree
. Siehe hier: Unterverzeichnis (Verschieben) in ein separates Git-Repository trennengit-subtree kann hierfür nützlich sein
http://github.com/apenwarr/git-subtree/blob/master/git-subtree.txt (veraltet)
http://psionides.jogger.pl/2010/02/04/sharing-code-between-projects-with-git-subtree/
quelle
Hier ist eine kleine Änderung an CoolAJ86 ‚s ‚The Easy Way ™‘Antwort zu spalten , um mehrere Unterordner (sagen wir mal
sub1
undsub2
) in eine neue git - Repository.The Easy Way ™ (mehrere Unterordner)
Bereiten Sie das alte Repo vor
Hinweis:
<name-of-folder>
darf KEINE führenden oder nachfolgenden Zeichen enthalten. Beispielsweise muss der Ordner mit dem Namensubproject
MUSS alssubproject
NICHT übergeben werden./subproject/
Hinweis für Windows-Benutzer: Wenn Ihre Ordnertiefe> 1 ist,
<name-of-folder>
muss das Ordnertrennzeichen (/) im * nix-Stil vorhanden sein. Beispielsweise muss der Ordner mit dem Namenpath1\path2\subproject
MUSS als übergeben werdenpath1/path2/subproject
. Verwenden Sie außerdem keinenmv
Befehl, abermove
.Letzte Anmerkung: Der einzigartige und große Unterschied zur Basisantwort ist die zweite Zeile des Skripts "
git filter-branch...
"Erstellen Sie das neue Repo
Verbinde das neue Repo mit Github oder wo auch immer
Aufräumen, falls gewünscht
Hinweis : Dadurch bleiben alle historischen Verweise im Repository erhalten. Lesen Sie den Anhang in der ursprünglichen Antwort, wenn Sie tatsächlich Bedenken haben, ein Kennwort festgeschrieben zu haben, oder wenn Sie die Dateigröße Ihres
.git
Ordners verringern müssen .quelle
sub1
undsub2
Ordner mit der ursprünglichen Version nicht vorhanden waren, musste ich mein--tree-filter
Skript wie folgt ändern :"mkdir <name-of-folder>; if [ -d sub1 ]; then mv <sub1> <name-of-folder>/; fi"
. Für den zweitenfilter-branch
Befehl habe ich <sub1> durch <sub2> ersetzt, die Erstellung von <name-of-folder> weggelassen und-f
danach eingefügt,filter-branch
um die Warnung einer vorhandenen Sicherung zu überschreiben.Die ursprüngliche Frage möchte, dass aus XYZ / ABC / (* -Dateien) ABC / ABC / (* -Dateien) werden. Nachdem ich die akzeptierte Antwort für meinen eigenen Code implementiert hatte, stellte ich fest, dass XYZ / ABC / (* Dateien) tatsächlich in ABC / (* Dateien) geändert wird. Die Filter-Zweig-Manpage sagt sogar:
Mit anderen Worten, der Ordner der obersten Ebene wird um eine Ebene "nach oben" befördert. Das ist eine wichtige Unterscheidung, weil ich beispielsweise in meiner Geschichte einen Ordner der obersten Ebene umbenannt hatte. Durch das Heraufstufen von Ordnern auf einer Ebene verliert git die Kontinuität bei dem Commit, bei dem ich die Umbenennung vorgenommen habe.
Meine Antwort auf die Frage lautet dann, 2 Kopien des Repositorys zu erstellen und die Ordner, die Sie in jedem behalten möchten, manuell zu löschen. Die Manpage unterstützt mich damit:
quelle
targetdir
hatte umbenannt irgendwann undgit filter-branch
einfach es einen Tag genannt, löscht alle Commits vor dem Umbenennungs gemacht! Schockierend, wenn man bedenkt, wie geschickt Git darin ist, solche Dinge zu verfolgen und sogar einzelne Inhaltsblöcke zu migrieren!git rm
mehrere Argumente erfordert, sodass es keinen Grund gibt, es für jede Datei / jeden Ordner auszuführen:BYEBYE="dir/subdir2 dir2 file1 dir/file2"; git filter-branch -f --index-filter "git rm -q -r -f --cached --ignore-unmatch $BYEBYE" --prune-empty -- --all
Um Pauls Antwort zu ergänzen, stellte ich fest, dass ich HEAD in ein sauberes Repository verschieben muss, um letztendlich Speicherplatz wiederherzustellen, und dass dadurch die Größe des Verzeichnisses .git / objects / pack verringert wird.
dh
Machen Sie nach dem GC-Schnitt auch:
Dann können Sie tun
und die Größe von ABC / .git wird reduziert
Tatsächlich sind einige der zeitaufwändigen Schritte (z. B. git gc) beim Push-to-Clean-Repository nicht erforderlich, z.
quelle
Der richtige Weg ist jetzt der folgende:
git filter-branch --prune-empty --subdirectory-filter FOLDER_NAME [first_branch] [another_branch]
GitHub hat jetzt sogar einen kleinen Artikel über solche Fälle.
Stellen Sie jedoch sicher, dass Sie Ihr ursprüngliches Repo zuerst in ein separates Verzeichnis klonen (da dadurch alle Dateien und anderen Verzeichnisse gelöscht werden und Sie wahrscheinlich damit arbeiten müssen).
Ihr Algorithmus sollte also sein:
git filter-branch
nur linke Dateien in einem Unterverzeichnis verwenden, drücken Sie auf eine neue Fernbedienungquelle
Es scheint, dass die meisten (alle?) Antworten hier auf irgendeiner Form
git filter-branch --subdirectory-filter
und ihrer Art beruhen. Dies kann jedoch "meistens" in einigen Fällen funktionieren, z. B. wenn Sie den Ordner umbenannt haben, z.Wenn Sie einen normalen Git-Filterstil verwenden, um "move_me_renamed" zu extrahieren, verlieren Sie den Änderungsverlauf der Datei, der von Anfang an aufgetreten ist, als es ursprünglich move_this_dir war ( ref ) war.
Es scheint also, dass die einzige Möglichkeit, den gesamten Änderungsverlauf wirklich beizubehalten (wenn Ihr Fall so ist), im Wesentlichen darin besteht, das Repository zu kopieren (ein neues Repo zu erstellen, das als Ursprung festzulegen) und dann alles andere zu zerstören und benennen Sie das Unterverzeichnis wie folgt in das übergeordnete Verzeichnis um:
git branch -a
git checkout --track origin/branchABC
cp -r oldmultimod simple
cd simple
git rm otherModule1 other2 other3
git mv moduleSubdir1/* .
rmdir moduleSubdir1
git status
git remote set-url origin http://mygithost:8080/git/our-splitted-module-repo
git remote -v
git push
git checkout branch2
Dies folgt dem Github-Dokument "Aufteilen eines Unterordners in ein neues Repository" in den Schritten 6 bis 11, um das Modul in ein neues Repo zu verschieben.
Dadurch sparen Sie keinen Speicherplatz in Ihrem .git-Ordner, aber der gesamte Änderungsverlauf für diese Dateien bleibt auch über Umbenennungen hinweg erhalten. Und das ist es vielleicht nicht wert, wenn nicht "viel" Geschichte verloren geht usw. Aber zumindest werden Sie garantiert keine älteren Commits verlieren!
quelle
Ich empfehle GitHubs Handbuch zum Aufteilen von Unterordnern in ein neues Repository . Die Schritte ähneln der Antwort von Paulus , aber ich fand ihre Anweisungen leichter zu verstehen.
Ich habe die Anweisungen so geändert, dass sie für ein lokales Repository gelten und nicht für ein auf GitHub gehostetes.
quelle
If you create a new clone of the repository, you won't lose any of your Git history or changes when you split a folder into a separate repository.
Laut Kommentaren zu allen Antworten hier führen sowohlfilter-branch
dassubtree
Skript als auch das Skript zum Verlust der Historie, wo immer ein Unterverzeichnis umbenannt wurde. Gibt es etwas, das getan werden kann, um dies zu beheben?Wenn Sie
git filter-branch
mit einer neueren Version vongit
(2.22+
vielleicht?) Ausführen , sollten Sie dieses neue Tool git-filter-repo verwenden . Dieses Tool hat mir sicherlich die Dinge vereinfacht.Filtern mit Filter-Repo
Befehle zum Erstellen des
XYZ
Repos aus der ursprünglichen Frage:Annahmen: * Remote-XYZ-Repo war vor dem Push neu und leer
Filtern und Bewegen
In meinem Fall wollte ich auch einige Verzeichnisse verschieben, um eine konsistentere Struktur zu erhalten. Anfangs habe ich diesen einfachen
filter-repo
Befehl ausgeführt, gefolgt vongit mv dir-to-rename
, aber ich habe festgestellt, dass ich mit dieser--path-rename
Option einen etwas "besseren" Verlauf erhalten kann . Anstatt zuletzt geänderte5 hours ago
Dateien im neuen Repo zu sehen, sehe ich jetztlast year
(in der GitHub-Benutzeroberfläche), was den geänderten Zeiten im ursprünglichen Repo entspricht.Anstatt...
Ich bin letztendlich gelaufen ...
Anmerkungen:git filter-repo --subdirectory-filter dir-matching-new-repo-name
). Dieser Befehl konvertierte dieses Unterverzeichnis korrekt in das Stammverzeichnis des kopierten lokalen Repos, führte jedoch auch zu einem Verlauf nur der drei Commits, die zum Erstellen des Unterverzeichnisses erforderlich waren. (Ich hatte nicht--path
bemerkt , dass dies mehrmals angegeben werden konnte, wodurch die Notwendigkeit entfiel, ein Unterverzeichnis im Quell-Repo zu erstellen.) Da sich jemand zum Quell-Repo verpflichtet hatte, als ich bemerkte, dass ich das nicht übertragen hatte Verlauf, den ich geradegit reset commit-before-subdir-move --hard
nach demclone
Befehl verwendet und dem Befehl hinzugefügt--force
habefilter-repo
, damit er auf dem leicht modifizierten lokalen Klon ausgeführt werden kann.git
, aber letztendlich habe ich Git-Filter-Repo geklont und es mit$(git --exec-path)
folgendem Link verknüpft :quelle
filter-repo
Tools (das ich letzten Monat in stackoverflow.com/a/58251653/6309 vorgestellt habe )git-filter-repo
sollte an dieser Stelle definitiv der bevorzugte Ansatz sein. Es ist viel, viel schneller und sicherer alsgit-filter-branch
und schützt vor vielen Fallstricken, auf die man stoßen kann, wenn man seine Git-Geschichte neu schreibt. Hoffentlich bekommt diese Antwort etwas mehr Aufmerksamkeit, da sie angesprochen werden mussgit-filter-repo
.Ich hatte genau dieses Problem, aber alle Standardlösungen, die auf Git Filter-Branch basierten, waren extrem langsam. Wenn Sie ein kleines Repository haben, ist dies möglicherweise kein Problem, es war für mich. Ich habe ein anderes Git-Filterprogramm geschrieben, das auf libgit2 basiert und in einem ersten Schritt Zweige für jede Filterung des primären Repositorys erstellt und diese dann als nächsten Schritt an saubere Repositorys weiterleitet. In meinem Repository (500 MB 100000 Commits) dauerten die Standardmethoden für Git-Filter-Verzweigungen Tage. Mein Programm benötigt Minuten, um dieselbe Filterung durchzuführen.
Es hat den fabelhaften Namen git_filter und lebt hier:
https://github.com/slobobaby/git_filter
auf GitHub.
Ich hoffe es ist nützlich für jemanden.
quelle
Verwenden Sie diesen Filterbefehl, um ein Unterverzeichnis zu entfernen und dabei Ihre Tags und Zweige beizubehalten:
quelle
Hier erfahren Sie, wie Sie GitHub auf einem Windows-Computer verwenden. Angenommen, Sie haben ein geklontes Repo, in dem Sie wohnen
C:\dir1
. Die Verzeichnisstruktur sieht folgendermaßen aus :C:\dir1\dir2\dir3
. Dasdir3
Verzeichnis ist das, für das ich ein neues separates Repo sein möchte.Github:
MyTeam/mynewrepo
Bash Prompt:
$ cd c:/Dir1
$ git filter-branch --prune-empty --subdirectory-filter dir2/dir3 HEAD
Ref 'refs/heads/master' was rewritten
Rückgabe : (fyi: dir2 / dir3 unterscheidet zwischen Groß- und Kleinschreibung.)$ git remote add some_name [email protected]:MyTeam/mynewrepo.git
git remote add origin etc
. hat nicht funktioniert, zurückgegeben "remote origin already exists
"$ git push --progress some_name master
quelle
Wie oben erwähnt , musste ich die umgekehrte Lösung verwenden (Löschen aller Commits, die meine nicht berühren
dir/subdir/targetdir
), die ziemlich gut zu funktionieren schien, wobei etwa 95% der Commits entfernt wurden (wie gewünscht). Es gibt jedoch noch zwei kleine Probleme.ZUERST ,
filter-branch
hat es geschafft, Commits zu entfernen, die Code einführen oder ändern, aber anscheinend befinden sich Merge-Commits unter seiner Station im Gitiverse.Dies ist ein kosmetisches Problem, mit dem ich wahrscheinlich leben kann (er sagt ... sich langsam mit abgewandten Augen zurückziehen) .
ZWEITENS sind die wenigen verbleibenden Commits so ziemlich ALLE dupliziert! Ich habe anscheinend eine zweite, redundante Zeitleiste erhalten, die fast die gesamte Geschichte des Projekts abdeckt. Das Interessante (was Sie auf dem Bild unten sehen können) ist, dass meine drei lokalen Niederlassungen nicht alle auf derselben Zeitachse liegen (weshalb es sicherlich existiert und nicht nur Müll gesammelt wird).
Das einzige, was ich mir vorstellen kann, ist, dass eines der gelöschten Commits möglicherweise das einzelne Merge-Commit war, das
filter-branch
tatsächlich gelöscht wurde , und das die parallele Zeitachse erstellt hat, als jeder jetzt nicht zusammengeführte Strang seine eigene Kopie der Commits erstellt hat. ( Achselzucken Wo sind meine TARDiS?) Ich bin mir ziemlich sicher, dass ich dieses Problem beheben kann, obwohl ich wirklich gerne verstehen würde, wie es passiert ist.Im Fall von verrücktem Mergefest-O-RAMA werde ich dieses wahrscheinlich in Ruhe lassen, da es sich so fest in meiner Commit-Geschichte verankert hat - bedrohlich für mich, wenn ich in die Nähe komme -, dass es nicht wirklich zu verursachen scheint alle nicht-kosmetischen Probleme und weil es in Tower.app ziemlich hübsch ist.
quelle
Der einfachere Weg
git splits
. Ich habe es als Git-Erweiterung erstellt, basierend auf der Lösung von jkeating .Teilen Sie die Verzeichnisse in einen lokalen Zweig auf
#change into your repo's directory cd /path/to/repo #checkout the branch git checkout XYZ
#split multiple directories into new branch XYZ git splits -b XYZ XY1 XY2
Erstellen Sie irgendwo ein leeres Repo. Wir gehen davon aus, dass wir
xyz
auf GitHub ein leeres Repo mit dem folgenden Pfad erstellt haben:[email protected]:simpliwp/xyz.git
Zum neuen Repo drücken.
#add a new remote origin for the empty repo so we can push to the empty repo on GitHub git remote add origin_xyz [email protected]:simpliwp/xyz.git #push the branch to the empty repo's master branch git push origin_xyz XYZ:master
Klonen Sie das neu erstellte Remote-Repo in ein neues lokales Verzeichnis
#change current directory out of the old repo cd /path/to/where/you/want/the/new/local/repo #clone the remote repo you just pushed to git clone [email protected]:simpliwp/xyz.git
quelle
git splits
)Möglicherweise benötigen Sie vor der Garbage Collection etwas wie "git reflog expire --expire = now --all", um die Dateien tatsächlich zu bereinigen. git filter-branch entfernt nur Verweise im Verlauf, entfernt jedoch nicht die Reflog-Einträge, die die Daten enthalten. Testen Sie dies natürlich zuerst.
Meine Festplattennutzung ging dabei dramatisch zurück, obwohl meine Anfangsbedingungen etwas anders waren. Vielleicht negiert --subdirectory-filter dieses Bedürfnis, aber ich bezweifle es.
quelle
Schauen Sie sich das git_split-Projekt unter https://github.com/vangorra/git_split an
Verwandeln Sie Git-Verzeichnisse in eigene Repositorys an ihrem eigenen Standort. Kein Teilbaum lustiges Geschäft. Dieses Skript nimmt ein vorhandenes Verzeichnis in Ihrem Git-Repository und verwandelt dieses Verzeichnis in ein eigenständiges Repository. Unterwegs wird der gesamte Änderungsverlauf für das von Ihnen angegebene Verzeichnis kopiert.
quelle
Fügen Sie dies in Ihre gitconfig ein:
quelle
Ich bin mir sicher, dass der Git-Teilbaum in Ordnung und wunderbar ist, aber meine Unterverzeichnisse mit git-verwaltetem Code, den ich verschieben wollte, waren alle in Eclipse. Wenn Sie also egit verwenden, ist es schmerzlich einfach. Nehmen Sie das Projekt, das Sie verschieben möchten, und teilen Sie es mit einem Team-> Trennen und anschließend mit einem Team-> am neuen Standort. Standardmäßig wird versucht, den alten Repo-Speicherort zu verwenden. Sie können jedoch die Auswahl für die Verwendung deaktivieren und den neuen Speicherort auswählen. Alle begrüßen egit.
quelle
Sie können ganz einfach das https://help.github.com/enterprise/2.15/user/articles/splitting-a-subfolder-out-into-a-new-repository/ ausprobieren.
Das hat bei mir funktioniert. Die Probleme, mit denen ich in den oben angegebenen Schritten konfrontiert war, sind
In diesem Befehl ist
git filter-branch --prune-empty --subdirectory-filter FOLDER-NAME BRANCH-NAME
TheBRANCH-NAME
is masterWenn der letzte Schritt beim Festschreiben aufgrund eines Schutzproblems fehlschlägt, gehen Sie wie folgt vor: https://docs.gitlab.com/ee/user/project/protected_branches.html
quelle
Ich habe eine recht einfache Lösung gefunden. Die Idee ist, das Repository zu kopieren und dann einfach unnötige Teile zu entfernen. So funktioniert es:
1) Klonen Sie ein Repository, das Sie teilen möchten
2) Wechseln Sie in den Git-Ordner
2) Entfernen Sie unnötige Ordner und schreiben Sie sie fest
3) Entfernen Sie mit BFG nicht benötigte Ordner aus dem Verlauf
4) Stellen Sie sicher, dass der Verlauf nicht die gerade gelöschten Dateien / Ordner enthält
5) Jetzt haben Sie ein sauberes Repository ohne ABC, also schieben Sie es einfach in einen neuen Ursprung
Das ist es. Sie können die Schritte wiederholen, um ein anderes Repository zu erhalten.
Entfernen Sie einfach XY1, XY2 und benennen Sie XYZ -> ABC in Schritt 3 um
quelle