Organizzazione dei repository Git con sotto-moduli nidificati comuni

48

Sono un grande fan dei sotto-moduli Git . Mi piace essere in grado di tenere traccia di una dipendenza insieme alla sua versione, in modo da poter eseguire il rollback a una versione precedente del progetto e avere la versione corrispondente della dipendenza per creare in modo sicuro e pulito. Inoltre, è più facile rilasciare le nostre librerie come progetti open source poiché la cronologia per le librerie è separata da quella delle applicazioni che dipendono da esse (e che non saranno open source).

Sto impostando il flusso di lavoro per più progetti sul lavoro, e mi chiedevo come sarebbe se avessimo adottato questo approccio un po 'estremo invece di avere un singolo progetto monolitico. Ho subito capito che esiste una potenziale lattina di worm in really usando i sub-moduli.

Supponendo una coppia di applicazioni: studio e player , e le librerie dipendenti core , graph e network , dove le dipendenze sono le seguenti:

  • core è indipendente
  • graph dipende da core (sottomodulo in ./libs/core )
  • network depdends su core (sub-module at ./libs/core )
  • studio dipende da graph e network (sotto-moduli a ./libs/graph e ./libs/network )
  • player dipende da graph e network (sotto-moduli a ./libs/graph e ./libs/network )

Supponiamo che stiamo usando CMake e che ognuno di questi progetti abbia test unitari e tutte le opere. Ogni progetto (incluso studio e player ) deve essere compilato autonomamente per eseguire metriche di codice, test di unità, ecc.

Il fatto è un git submodule fetch ricorsivo, quindi si ottiene la seguente struttura di directory:

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/

Tieni presente che core viene clonato due volte nel progetto studio . A parte questo spreco di spazio su disco, ho un problema con il sistema di build perché sto creando core due volte e potenzialmente ho due versioni diverse di core .

Domanda

Come organizzo i sottomoduli in modo da ottenere la dipendenza dalla versione e la compilazione autonoma senza ottenere più copie di sottomoduli nidificati comuni?

Possibile soluzione

Se la dipendenza della libreria è in qualche modo un suggerimento (cioè in un "noto per lavorare con la versione X" o "solo la versione X è ufficialmente supportata") e le potenziali applicazioni o librerie dipendenti sono responsabili della creazione con qualsiasi versione come, quindi potrei immaginare il seguente scenario:

  • Avere il sistema di compilazione per graph e network per indicare dove trovare core (ad es. tramite un percorso di inclusione del compilatore). Definisci due target di build, "standalone" e "dependency", dove "standalone" è basato su "dependency" e aggiunge il percorso include a puntare al sottomodulo core locale.
  • Introduci una dipendenza extra: studio su core . Quindi, studio crea core , imposta il percorso di inclusione sulla propria copia del sottomodulo core , quindi crea graph e network in modalità "dipendenza".

La struttura della cartella risultante assomiglia a:

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)

Tuttavia, questo richiede un po 'di magia del sistema di build (sono abbastanza sicuro che questo possa essere fatto con CMake) e un po' di lavoro manuale da parte degli aggiornamenti di versione (l'aggiornamento di graph potrebbe anche richiedere l'aggiornamento di core e network per ottenere una versione compatibile di core in tutti i progetti).

Qualche idea su questo?

    
posta André Caron 17.10.2011 - 17:37
fonte

5 risposte

5

Sono molto in ritardo per questa festa, ma la tua domanda non sembra avere ancora una risposta completa, ed è un successo piuttosto evidente da parte di Google.

Ho lo stesso identico problema con C ++ / CMake / Git / Submodule e ho un problema simile con MATLAB / Git / Submodules, che ottiene qualche stranezza in più perché MATLAB non è compilato. Mi sono imbattuto recentemente in questo video , che sembra proporre una "soluzione". Non mi piace la soluzione, perché essenzialmente significa buttare via i sottomoduli, ma elimina il problema. È proprio come @errordeveloper consiglia. Ogni progetto non ha sottomoduli. Per creare un progetto, crea un super progetto per costruirlo e includerlo come fratello alle sue dipendenze.

Quindi il tuo progetto per lo sviluppo di graph potrebbe essere simile a:

buildgraph/graph
buildgraph/core

e quindi il tuo progetto per studio potrebbe essere:

buildstudio/studio
buildstudio/graph
buildstudio/network
buildstudio/core

I super-progetti sono solo un CMakeLists.txt principale e un gruppo di sottomoduli. Ma nessuno dei progetti ha alcun sottomodulo.

L'unico costo che vedo per questo approccio è la proliferazione di "super-progetti" banali che sono solo dedicati alla costruzione dei tuoi progetti reali. E se qualcuno prende in mano uno dei tuoi progetti, non c'è un modo semplice per dirlo senza trovare il super-progetto, quali sono le sue dipendenze. Ad esempio, questo potrebbe renderlo davvero brutto su Github.

    
risposta data 28.07.2016 - 15:18
fonte
1

Suppongo che quando si integrano entrambi graph e network sottomoduli in studio , è sempre necessario avere la stessa versione di core in un dato momento nella cronologia di studio . Vorrei simlinkare il submodule studio/libs/core in studio/libs/{graph,network}/libs .

Aggiornamento:

Ho creato più repository con le dipendenze che hai dichiarato:

./core      <--- (v2)
./graph
./graph/libs
./graph/libs/core  <--- (v2)
./graph/.gitmodules
./network
./network/libs
./network/libs/core  <--- (v1)
./network/.gitmodules
./studio
./studio/libs
./studio/libs/graph
./studio/libs/graph/libs
./studio/libs/graph/libs/core <--- (v1)
./studio/libs/graph/.gitmodules
./studio/libs/network
./studio/libs/network/libs
./studio/libs/network/libs/core  <--- (v1)
./studio/libs/network/.gitmodules
./studio/studio
./studio/.gitmodules

v1 e v2 sono due versioni diverse di core . graph gestisce la versione 2, mentre network ha bisogno di un po 'di lavoro ed è bloccato alla versione 1. In studio , le versioni locali incorporate di core puntano entrambe a v1 per avere un programma funzionante. Ora, a parte la prospettiva di costruzione, tutto funziona bene con i sottomoduli.

Ora posso rimuovere la seguente directory:

./studio/libs/network/libs/core

E sostituiscilo con un link simbolico:

./studio/libs/network/libs/core@ -> ../../graph/libs/core/

Apporto localmente questo cambiamento e perdo la possibilità di avere due versioni separate di core all'interno di studio , ma creo solo core una volta. Quando sono pronto per l'aggiornamento a v2 , posso fare:

 git submodule update # (--rebase ?)

... all'interno di studio / libs / network.

    
risposta data 10.11.2011 - 22:11
fonte
0

Lo appiattirei per avere una profondità di sottomodulo di uno solo e disporre di un repository che conserverebbe tutti i moduli come sotto-moduli e nient'altro che README e gli script di compilazione. Ci sarebbe uno script di compilazione separato per ciascuno dei pacchetti che collegano le sue dipendenze. Altrimenti puoi avere un repository separato per un pacchetto.

    
risposta data 17.10.2011 - 22:34
fonte
0

Non userei i sottomoduli.

È allettante, come nel caso degli svn-esterni. Tuttavia, puoi essere sicuro che tutti i progetti che colleghi sono ancora nello stesso posto in un anno? Che ne dici di cinque?

Pertanto, sto semplicemente copiando tutte le dipendenze richieste nel mio progetto. Ciò significa che finché il mio repo è valido, posso verificare lo stato esatto.

Fondamentalmente, ho una struttura di cartelle come segue:

myproject/... [sources etc]
ext/ [third-party dependencies]


e.g. ext/boost, ext/cppunit

Sebbene ciò non sia molto bello dal punto di vista dello spazio su disco, apprezzo la garanzia di poter controllare ogni stato registrato finché il repository è disponibile molto più alto.

Inoltre, ci sono un sacco di problemi con i sottomoduli come descritto qui

    
risposta data 30.04.2013 - 14:08
fonte
0

Affrontare esattamente lo stesso problema qui. Una delle soluzioni potrebbe essere quella di avere un repo libs che potrebbe contenere core , network , graph come submoduli e solo CMakeLists che direbbero a ciascuna delle librerie dove trovare le sue dipendenze. Ogni applicazione ora avrà libs come submodule e utilizzerà solo le librerie necessarie.

Il test di ogni lib potrebbe essere configurato in 2 modi:

  • Avere core_testing, graph_testing, test di rete come applicazioni separate
  • Distribuire le librerie testate ai server di test e trovarle durante l'esecuzione dei test utilizzando cmake
risposta data 24.12.2015 - 15:54
fonte

Leggi altre domande sui tag