Sehr oft schreiben Sie ein Projekt, und nach einer Weile wird klar, dass eine Komponente des Projekts tatsächlich als eigenständige Komponente (möglicherweise eine Bibliothek) nützlich ist. Wenn Sie diese Idee von Anfang an hatten, besteht eine gute Chance, dass sich der größte Teil dieses Codes in einem eigenen Ordner befindet.
Gibt es eine Möglichkeit, eines der Unterverzeichnisse in einem Git-Projekt in ein Submodul zu konvertieren?
Im Idealfall geschieht dies so, dass der gesamte Code in diesem Verzeichnis aus dem übergeordneten Projekt entfernt wird und das Submodulprojekt an seiner Stelle mit dem entsprechenden Verlauf hinzugefügt wird und alle Commits des übergeordneten Projekts auf die richtigen Commits des Submoduls verweisen .
git
git-submodules
naught101
quelle
quelle
Antworten:
Verwenden Sie
filter-branch
auf einem Klon des ursprünglichen Repositorys Folgendes, um ein Unterverzeichnis in ein eigenes Repository zu isolieren :Es ist dann nichts weiter als das Löschen Ihres ursprünglichen Verzeichnisses und das Hinzufügen des Submoduls zu Ihrem übergeordneten Projekt.
quelle
git remote rm <name>
nach dem Filterzweig eine neue Fernbedienung hinzufügen. Auch wenn es ignorierte Dateien gibt,git clean -xd -f
kann a nützlich sein-- --all
kann durch den Namen eines Zweigs ersetzt werden, wenn das Submodul nur aus diesem Zweig extrahiert werden soll.git clone <your_project> <your_submodule>
nur Download - Dateien für your_submodule?git clone source destination
teilt Git einfach mit, wo sich Ihre geklonten Dateien befinden sollen. Die eigentliche Magie zum Filtern der Dateien Ihres Submoduls geschieht dann imfilter-branch
Schritt.filter-branch
ist heutzutage veraltet . Sie können verwendengit clone --filter
, aber Ihr Git-Server muss so konfiguriert sein, dass Filterung möglich ist, sonst erhalten Siewarning: filtering not recognized by server, ignoring
.Ändern Sie zuerst das Verzeichnis in einen Ordner, der ein Submodul sein wird. Dann:
quelle
Ich weiß, dass dies ein alter Thread ist, aber die Antworten hier unterdrücken alle damit verbundenen Commits in anderen Branchen.
Eine einfache Möglichkeit, all diese zusätzlichen Zweige und Commits zu klonen und zu behalten:
1 - Stellen Sie sicher, dass Sie diesen Git-Alias haben
2 - Klonen Sie die Fernbedienung, ziehen Sie alle Zweige, wechseln Sie die Fernbedienung, filtern Sie Ihr Verzeichnis und drücken Sie
quelle
Es kann getan werden, aber es ist nicht einfach. Wenn Sie suchen
git filter-branch
,subdirectory
undsubmodule
gibt es ein paar anständige Zuschreibung auf den Prozess. Im Wesentlichen müssen zwei Klone Ihres Projekts erstellt werden, mit denengit filter-branch
alles außer dem einen Unterverzeichnis in einem entfernt wird und nur dieses Unterverzeichnis im anderen entfernt wird. Anschließend können Sie das zweite Repository als Submodul des ersten einrichten.quelle
Status Quo
Nehmen wir an , wir haben ein Repository, genannt ,
repo-old
die eine Unter enthält Verzeichnissub
, dass wir in eine Unter umwandeln möchte Modul mit einem eigenen Reporepo-sub
.Es ist ferner beabsichtigt, das ursprüngliche Repo
repo-old
in ein modifiziertes Repo umzuwandeln,repo-new
wobei alle Commits, die das zuvor vorhandene Unterverzeichnis berührensub
, nun auf die entsprechenden Commits unseres extrahierten Submodul-Repos verweisenrepo-sub
.Lass uns ändern
Dies kann mit Hilfe
git filter-branch
eines zweistufigen Prozesses erreicht werden:repo-old
bisrepo-sub
(bereits in der akzeptierten Antwort erwähnt )repo-old
bisrepo-new
(mit ordnungsgemäßer Festschreibungszuordnung)Bemerkung : Ich weiß, dass diese Frage alt ist und bereits erwähnt wurde, dass sie
git filter-branch
veraltet ist und gefährlich sein könnte. Auf der anderen Seite kann es anderen helfen, persönliche Repositorys zu erstellen, die nach der Konvertierung leicht zu validieren sind. Also sei gewarnt ! Und bitte lassen Sie mich wissen, ob es ein anderes Tool gibt, das dasselbe tut, ohne veraltet zu sein und sicher zu verwenden ist!Ich werde erklären, wie ich beide Schritte unter Linux mit der Git-Version 2.26.2 realisiert habe. Ältere Versionen funktionieren möglicherweise bis zu einem gewissen Grad, dies muss jedoch getestet werden.
Der Einfachheit halber beschränke ich mich auf den Fall, dass das ursprüngliche Repo nur einen
master
Zweig und eineorigin
Fernbedienung enthältrepo-old
. Seien Sie auch gewarnt, dass ich mich auf temporäre Git-Tags mit dem Präfix verlasse,temp_
die dabei entfernt werden. Wenn also bereits Tags mit ähnlichen Namen vorhanden sind, können Sie das folgende Präfix anpassen. Und zum Schluss beachten Sie bitte, dass ich dies nicht ausführlich getestet habe und es möglicherweise Eckfälle gibt, in denen das Rezept fehlschlägt. Bitte sichern Sie alles, bevor Sie fortfahren !Die folgenden Bash-Snippets können zu einem großen Skript verkettet werden, das dann in demselben Ordner ausgeführt werden soll, in dem sich das Repo befindet
repo-org
. Es wird nicht empfohlen, alles direkt in ein Befehlsfenster zu kopieren und einzufügen (obwohl ich dies erfolgreich getestet habe)!0. Vorbereitung
Variablen
Filterskript
1. Extraktion des Unterverzeichnisses
2. Austausch des Unterverzeichnisses
Anmerkung: Wenn das neu erstellte Repo
repo-new
währenddessen hängt,git submodule update --init
versuchen Sie stattdessen, das Repository einmal rekursiv neu zu klonen:quelle
Dies führt die Konvertierung direkt durch. Sie können sie wie jeden Filterzweig (den ich verwende
git fetch . +refs/original/*:*
) zurücksetzen .Ich habe ein Projekt mit einer
utils
Bibliothek, die in anderen Projekten nützlich ist, und wollte ihre Geschichte in Submodule aufteilen. Ich habe nicht daran gedacht, zuerst auf SO zu schauen, also habe ich mein eigenes geschrieben. Es erstellt den Verlauf lokal, so dass es ein gutes Stück schneller ist. Danach können Sie, wenn Sie möchten, die Hilfsbefehle einrichten.gitmodules
Datei Hilfsbefehls und dergleichen und die Submodulverläufe selbst an eine beliebige Stelle verschieben Sie wollen.Der Befehl zum Entfernen ist hier, das Dokument in den Kommentaren, in dem folgenden, der nicht entfernt wurde. Führen Sie es als eigenen Befehl mit
subdir
set aus, als würdensubdir=utils git split-submodule
Sie dasutils
Verzeichnis aufteilen . Es ist hacky, weil es einmalig ist, aber ich habe es im Unterverzeichnis Documentation im Git-Verlauf getestet.quelle