Ich bin ein großer Fan von Git-Submodulen . Ich möchte in der Lage sein, eine Abhängigkeit zusammen mit ihrer Version zu verfolgen, so dass Sie ein Rollback auf eine frühere Version Ihres Projekts durchführen und die entsprechende Version der Abhängigkeit sicher und sauber erstellen können. Darüber hinaus ist es einfacher, unsere Bibliotheken als Open-Source-Projekte freizugeben, da die Historie für Bibliotheken von der der Anwendungen, die von ihnen abhängen (und die nicht aus Open-Source-Quellen stammen), getrennt ist.
Ich richte den Workflow für mehrere Projekte bei der Arbeit ein und fragte mich, wie es wohl wäre, wenn wir diesen Ansatz ein wenig extrem nehmen würden, anstatt nur ein einziges monolithisches Projekt zu haben. Ich stellte schnell fest, dass es eine potenzielle Dose Würmer gibt, wenn man wirklich Submodule verwendet.
Nimmt man ein Paar von Anwendungen: studio
und player
, und abhängigen Bibliotheken core
, graph
und network
, wo Abhängigkeiten sind wie folgt:
core
ist eigenständiggraph
abhängig voncore
(Submodul bei./libs/core
)network
abhängig voncore
( Submodul bei./libs/core
)studio
abhängig vongraph
undnetwork
(Untermodule bei./libs/graph
und./libs/network
)player
abhängig vongraph
undnetwork
(Untermodule bei./libs/graph
und./libs/network
)
Angenommen, wir verwenden CMake und jedes dieser Projekte hat Unit-Tests und alle Arbeiten. Jedes Projekt (einschließlich studio
und player
) muss eigenständig kompiliert werden können, um Codemetriken, Komponententests usw. durchzuführen.
Die Sache ist, eine rekursive git submodule fetch
, dann erhalten Sie die folgende Verzeichnisstruktur:
studio/
studio/libs/ (sub-module depth: 1)
studio/libs/graph/
studio/libs/graph/libs/ (sub-module depth: 2)
studio/libs/graph/libs/core/
studio/libs/network/
studio/libs/network/libs/ (sub-module depth: 2)
studio/libs/network/libs/core/
Beachten Sie, dass core
im studio
Projekt zweimal geklont wird . Abgesehen von dieser Verschwendung von Speicherplatz habe ich ein Build-System-Problem, weil ich core
zweimal baue und möglicherweise zwei verschiedene Versionen von bekomme core
.
Frage
Wie organisiere ich Submodule, damit ich die versionierte Abhängigkeit und den Standalone-Build erhalte, ohne mehrere Kopien von häufig verschachtelten Submodulen zu erhalten?
Mögliche Lösung
Wenn die Bibliotheksabhängigkeit eher ein Vorschlag ist (dh "bekanntermaßen mit Version X arbeiten" oder "nur Version X wird offiziell unterstützt") und potenziell abhängige Anwendungen oder Bibliotheken für die Erstellung mit einer beliebigen Version verantwortlich sind, dann Ich könnte mir folgendes Szenario vorstellen:
- Haben Sie das Build-System für
graph
undnetwork
teilen Sie ihnen mit, wo sie zu finden sindcore
(z. B. über einen Compiler-Include-Pfad). Definieren Sie zwei Build-Ziele, "Standalone" und "Abhängigkeit", wobei "Standalone" auf "Abhängigkeit" basiert und den Include-Pfad hinzufügt, der auf das lokalecore
Untermodul verweist. - Fügen Sie eine zusätzliche Abhängigkeit hinzu:
studio
oncore
. Dannstudio
bautcore
, setzt den Include-Pfad auf seine eigene Kopie descore
Submoduls, baut danngraph
undnetwork
im "Abhängigkeits" -Modus.
Die resultierende Ordnerstruktur sieht folgendermaßen aus:
studio/
studio/libs/ (sub-module depth: 1)
studio/libs/core/
studio/libs/graph/
studio/libs/graph/libs/ (empty folder, sub-modules not fetched)
studio/libs/network/
studio/libs/network/libs/ (empty folder, sub-modules not fetched)
Dies erfordert jedoch etwas Magie für das Build-System (ich bin mir ziemlich sicher, dass dies mit CMake möglich ist) und ein wenig manuelle Arbeit seitens der Versionsaktualisierungen (Aktualisierungen graph
erfordern möglicherweise auch Aktualisierungen core
und network
eine kompatible Version von core
allen Projekten). .
Irgendwelche Gedanken dazu?
quelle
Antworten:
Ich komme sehr spät zu dieser Party, aber Ihre Frage scheint immer noch keine vollständige Antwort zu haben, und es ist ein ziemlich prominenter Hit von Google.
Ich habe genau das gleiche Problem mit C ++ / CMake / Git / Submodules und ich habe ein ähnliches Problem mit MATLAB / Git / Submodules, das eine zusätzliche Verrücktheit bekommt, weil MATLAB nicht kompiliert wird. Ich bin vor kurzem auf dieses Video gestoßen, das eine "Lösung" vorzuschlagen scheint. Ich mag die Lösung nicht, weil es im Wesentlichen bedeutet, Submodule wegzuwerfen, aber es beseitigt das Problem. Es ist genau so, wie @errordeveloper empfiehlt. Jedes Projekt hat keine Submodule. Um ein Projekt zu erstellen, erstellen Sie ein Superprojekt, um es zu erstellen, und fügen Sie es den Abhängigkeiten gleich.
Ihr Entwicklungsprojekt
graph
könnte also so aussehen:und dann könnte dein Projekt für Studio sein:
Die Superprojekte sind nur ein Haupt-
CMakeLists.txt
und ein Bündel von Submodulen. Keines der Projekte verfügt jedoch über eigene Submodule.Die einzigen Kosten, die ich für diesen Ansatz sehe, sind die vielen kleinen "Super-Projekte", die nur dem Aufbau Ihrer echten Projekte gewidmet sind. Und wenn jemand eines Ihrer Projekte in den Griff bekommt, gibt es keine einfache Möglichkeit, die Abhängigkeiten des Superprojekts zu ermitteln. Das könnte es zum Beispiel hässlich machen, auf Github zu sitzen.
quelle
Ich nehme an, wenn Sie sowohl Module
graph
als auchnetwork
Submodule integrierenstudio
, müssen Siecore
in der Geschichte von immer dieselbe Version von zu einem bestimmten Zeitpunkt habenstudio
. Ich würde dasstudio/libs/core
Submodul in simlinkenstudio/libs/{graph,network}/libs
.Aktualisieren:
Ich habe mehrere Repositorys mit den von Ihnen angegebenen Abhängigkeiten erstellt:
v1
undv2
sind zwei verschiedene Versionen voncore
.graph
behandelt Version 2, währendnetwork
einige Arbeit benötigt und bei Version 1 steckt. Instudio
den lokalen eingebetteten Versionen voncore
beiden wird daraufv1
hingewiesen, um ein funktionierendes Programm zu haben. Abgesehen von der Build-Perspektive funktioniert jetzt alles gut mit Submodulen.Ich kann jetzt das folgende Verzeichnis entfernen:
Und ersetze es durch einen symbolischen Link:
Ich setze diese Änderung lokal um und verliere die Fähigkeit, zwei separate Versionen von
core
inside zu habenstudio
, aber ich baue nurcore
einmal. Wenn ich zum Upgrade bereitv2
bin, kann ich Folgendes tun:... in studio / libs / network.
quelle
graph/libs/core
außen verlinken , verwenden Sie das Submodul nicht. Wenn Sie eine Verknüpfungstudio/libs/core
zu einer der Bibliotheken des Submoduls herstellen, welche wählen Sie dann aus,graph
odernetwork
? Was passiert außerdem, wenn es drei oder mehr Schichten tief ist? Was ist, wenncore
es eine Reihe von Revisionen geben kann? Es ist nicht offensichtlich , dass Sie zu jeder Version verknüpfen möchten ,core
dassgraph
undnetwork
verwenden.core
wäre ein Submodul, das aus der Originalbibliothekcore
abgerufen und auf eine Version aktualisiert wird, die mit beidengraph
und kompatibel istnetwork
(Sie müssen entscheiden, welches gut ist). Die symbolischen Verknüpfungen werden im lokalengraph
und imnetwork
Submodul hinzugefügt (nicht abgerufen).graph
undnetwork
außerhalb ihres eigenen Repository (zB irgendwo anders im Punkt würdestudio
Projekt). Woher wissen sie, wann sie ihr eigenes Untermodul verwenden müssen und wann sie den symbolischen Link verwenden müssen? Vielleicht sollten Sie ein Beispiel hinzufügen, um Ihre Denkweise zu demonstrieren.Ich würde es auf eine Submodultiefe von nur einem reduzieren und ein Repository haben, das alle Module als Submodule und nichts anderes außer README und den Build-Skripten enthält. Für jedes der Pakete, die seine Abhängigkeiten verknüpfen, gibt es ein separates Erstellungsskript. Andernfalls können Sie für ein Paket ein separates Repo haben.
quelle
Ich würde keine Submodule verwenden.
Es ist verlockend, so wie es früher bei svn-externals der Fall war. Können Sie jedoch sicher sein, dass sich alle Projekte, die Sie verknüpfen, in einem Jahr noch am selben Ort befinden? Was ist mit in fünf?
Daher kopiere ich einfach alle erforderlichen Abhängigkeiten in mein Projekt. Dies bedeutet, dass ich, solange mein Repo gültig ist, den genauen Status überprüfen kann.
Grundsätzlich habe ich eine Ordnerstruktur wie folgt:
Obwohl dies aus Sicht des Festplattenspeichers nicht sehr schön ist, schätze ich die Garantie, dass ich jeden aufgezeichneten Status überprüfen kann, solange das Repo viel höher verfügbar ist.
Darüber hinaus gibt es eine Reihe von Problemen mit Submodulen, wie hier beschrieben
quelle
Genau das gleiche Problem hier konfrontiert. Eine der Lösungen könnte sein , einige Repo zu haben ,
libs
die halten würdecore
,network
,graph
als Submodule und nur CMakeLists , dass jeder der Libs sagen würde , wo ihre Abhängigkeiten zu finden. Jede Anwendung würde jetztlibs
als Submodul und nur die notwendigen Bibliotheken verwenden.Das Testen jeder Bibliothek kann auf zwei Arten erfolgen:
quelle
graph
nichts darüber wissen müssennetwork
- geben Sie keine relevanten Informationennetwork
angraph
subdir weiter