2009-09-14 16 views
43

Diciamo che hanno quattro progetti denominati Nucleo, A, B, Super. L'albero delle dipendenze è come questo:sottomoduli Git nidificate e le dipendenze

Super ---> Core 
     |-> A -> Core 
     |-> B -> Core 

Voglio ogni progetto sia stand-alone, cioè, voglio essere in grado di check-out e compilare ogni progetto da solo (ognuno con le sue dipendenze, naturalmente).

ho pensato di mappatura ogni progetto in un repository e poi riferendosi dipendenze con moduli, ma vedo i seguenti problemi con questo approccio:

  1. Al check-out Super con tutte le sue dipendenze, mi piacerebbe finire con tre copie di Core.
  2. Poiché i sottomoduli sono completamente indipendenti, ciascuna di queste tre copie potrebbe indicare diverse revisioni di Core e sarebbe un disastro.

Quindi ... Mi manca qualcosa? Ho frainteso male i sottomoduli o li ho usati male? C'è qualche altra soluzione a questo problema (oltre al ricorso alle dipendenze binarie)?

risposta

12

Hai appena scoperto la mancanza di dipendenze override con sottomoduli git:

Se Super dipende dal Nucleo, la dipendenza del core dovrebbe "override" quelli A e B hanno Core.

L'unico modo per emulare il che sarebbe per creare il progetto Super il modo in cui l'avete fatto,
e per rimuovere il nucleo sottomodulo di A e B.
(che significa Super dipende ora in A' e B ', A' essere A senza Core, B 'essere B senza Core)

7

I repository git devono essere abbastanza atomici nel modo in cui ciascun repository è un'entità autonoma per uno scopo specifico. Qual è lo scopo del super progetto diverso dalla combinazione dei progetti A e B? Se non c'è nulla di unico (cioè i file che non sono in A, B o Core), allora è abbastanza ridondante.

EDIT: Poiché i sottomoduli git sono particolarmente dolorosi in un punto in cui ho lavorato, abbiamo creato il nostro sistema di dipendenza che tiene traccia dei repository dipendenti tramite file di testo. Lo impostiamo in modo da tenere sempre traccia della testa di un ramo, non di un commit particolare.

Siamo stati in grado di impostare tutti i nostri progetti come se fossero una parte del progetto Super come questo:

Super 
|-A 
|-B 
|-Core 

I progetti di riferimento tra loro utilizzando percorsi relativi per esempio ../A/include.h. Check-out repo A non funziona, si dovrebbe creare un altro repo "super" per lavorare solo su A:

AWorking 
|-A 
|-Core 

EDIT Un altro motivo per questo comportamento in git è che non si può tenere traccia delle cose che sono sopra la directory root repo (cioè sopra la cartella contenente la cartella .git), che sarebbe sicuramente necessaria se vuoi che i tuoi super-progetti e sotto-progetti facciano riferimento agli stessi repository.

+0

Super è un progetto in sé. Non dare per scontato che non abbia contenuto solo perché l'ho chiamato Super. –

+1

Ma voglio che ogni progetto sia indipendente. E mi piace che i sottomoduli git siano corretti su un commit particolare invece di seguire come gli svn esterni, in modo che una modifica in Core non rompa immediatamente A, B e Super. –

+1

Indipendentemente dal fatto che segui i rami o esegui il commit degli SHA. Ma la risposta migliore per il tuo problema è che non è davvero possibile avere l'opzione stand-alone e il super-progetto. In pratica ho scoperto che avere un super progetto per ogni sottoprogetto non è un grosso problema. –

0

Non vorrei provare a mappare un albero delle dipendenze con sotto-moduli - per i motivi che hai già scoperto.

I sottomoduli seguono una determinata revisione di un determinato ramo, quindi sono utili per fornire un'istantanea di un insieme coerente di moduli.

Quindi, se il progetto richiede una determinata serie di versioni di diversi moduli da monitorare come un'unica unità, è possibile raggrupparle come sottomoduli.È quindi possibile contrassegnare diversi set di moduli con versioni diverse, per fornire una cronologia del progetto, in cui ogni tag mostra quali versioni di quali moduli erano compatibili in un determinato momento.

tags/ 
    release1/ 
      |-> [email protected] 
      |-> [email protected] 
      |-> [email protected] 
    release2/ 
      |-> [email protected] 
      |-> [email protected] 
      |-> [email protected] 

Almeno questo come li capisco, anche se come la maggior parte le cose con Git, probabilmente c'è molto di più ad esso che quello. In termini di gestione delle dipendenze, tutto quello che posso dire è trovare un altro modo, non è quello che è stato progettato per Git con o senza i sottomodelli, come ho capito.

+0

Ok ... ma penso che questo risolva un problema diverso ... non quello che sto chiedendo. –

6

Penso che il problema qui sia una discrepanza tra la progettazione di Git e il problema che si sta cercando di risolvere.

Git è buono per tenere traccia degli alberi. Le relazioni di dipendenza tra progetti possono (e probabilmente lo fanno) formare un grafico. Un albero è un grafico ma un grafico non è necessariamente un albero. Poiché il tuo problema è come rappresentare efficacemente un grafico, un albero non è lo strumento migliore per il lavoro.

Ecco un approccio che potrebbe funzionare:

Un progetto Git ha una directory .gitmodules dove si registra "suggerimenti", affermando che proietta un commit può dipendere, dove possono essere trovati, e quale percorso all'interno del progetto dovrebbero essere inseriti in (http://osdir.com/ml/git/2009-04/msg00746.html)

È possibile aggiungere uno script che legge queste informazioni da un insieme di progetti, mappare gli hint trovati nel file .gitmodules di ciascun progetto nelle posizioni sul file system in cui sono stati effettivamente posizionati tali progetti e quindi aggiunge simboli collegamenti dai percorsi in cui git prevede di controllare i sottomoduli nelle posizioni dei filesystem effettivi dei rispettivi progetti.

Questo approccio utilizza collegamenti simbolici per uscire dallo stampo Albero e creare un grafico. Se registriamo i collegamenti direttamente in repository git, avremmo percorsi relativi specifici per la nostra configurazione locale registrati nei singoli progetti, e i progetti non sarebbero "completamente indipendenti" come volevi. Quindi, lo script per creare dinamicamente i collegamenti simbolici.

Sto pensando che questo approccio potrebbe interferire con git in modi indesiderati, dal momento che abbiamo intrapreso percorsi in cui ci si aspetta di trovare una cosa, e invece mettere qualcos'altro lì. Forse potremmo .gitignore i percorsi dei link simbolici. Ma ora stiamo scrivendo quei percorsi due volte e violando DRY. A questo punto siamo anche andati molto lontano dal fingere di usare i sottomoduli. Potremmo registrare le dipendenze altrove in ogni progetto e lasciare il file .gitmodules per le cose che git si aspetta. Quindi creeremo il nostro file, diciamo, .dipendenze, e ogni progetto può indicarne le dipendenze. Il nostro script guarderà lì e poi andrà a costruire i suoi symlink.

Hmm, penso che forse ho appena descritto un sistema di gestione dei pacchetti ad hoc, con un proprio formato di pacchetto leggero :) suggerimento

di megamic sembra un buon uso di sottomoduli git a me.Ci occupiamo solo di tenere traccia di un Set qui piuttosto che di un Grafico, e un Set si adatta facilmente ad un Albero. Un albero ad un livello profondo è essenzialmente un nodo genitore e un insieme di nodi figli.

Come hai sottolineato, ciò non risolve completamente il problema indicato nella tua domanda. Possiamo distinguere due distinti tipi di "questo funziona con quello" informazioni che probabilmente sono interessate a: 1. Una dichiarazione da una versione di un progetto (presumibilmente dall'autore del progetto) che dice "Richiedo la versione X del progetto Y" 2. Una dichiarazione usata dal proprio setup di costruzione che dice "Ho testato con successo tutto il nostro sistema usando questo insieme di versioni di progetto"

risposta di megamic risolta (2) ma per (1) vogliamo ancora che i progetti ci dicano quali sono le loro dipendenze. Quindi possiamo usare le informazioni da (1) per calcolare quei set di versioni che finiremo per registrare come (2). Questo è un problema abbastanza complesso da giustificare il proprio strumento, che ci riporta ai sistemi di gestione dei pacchetti :)

Per quanto ne so, la maggior parte dei buoni strumenti di gestione dei pacchetti sono realizzati per gli utenti di un linguaggio o sistema operativo specifico . Vedi Bundler per pacchetti "gem" nel mondo ruby ​​e apt per pacchetti ".deb" nel mondo Debian.

Se qualcuno sa di una buona soluzione neutra, neutrale rispetto al sistema operativo, adatta ai progetti di programmazione "poliglotta" (http://blog.heroku.com/archives/2011/8/3/polyglot_platform/), sarei molto interessato! Dovrei postarlo come una domanda.

+1

+1 Poiché il tuo problema è come rappresentare efficacemente un grafico, un albero non è lo strumento migliore per il lavoro. –

2

Penso che tu possa gestire la coerenza in questo modo: definisci un ramo "di riferimento" o una serie di tag con lo stesso nome (s) in tutte le tue librerie "Core" (nota: c'è solo una libreria "Core" nella tua esempio). Quindi istruisci gli sviluppatori di sottoprogetti (A, B, ...) per aggiornare regolarmente alla versione di riferimento di "Core" non appena possibile.

Prima di eseguire una compilazione, controllare facilmente che "Core (s)" sia utilizzato coerentemente su A, B, C, ... eseguendo questi tre comandi in un checkout pulito, ricorsivo, "Super", di livello superiore :

# 1. Switch to the reference version (= "Force" consistency where need be) 
git submodule foreach --recursive 'git checkout [origin/]reference || true' 

# 2a. Show which inconsistencies you just forced; terse output 
git status -s; git submodule foreach --recursive git status -s 2>/dev/null 

# 2b. Same but verbose output 
git submodule; git submodule foreach --recursive git submodule 

# 3. Switch back to versions individually defined by sub-projects 
git submodule update --recursive 

il "Terse uscita" comando 2a sopra evidenzia che sotto-progetto (s) non si utilizza la versione "di riferimento" core.

È possibile estendere facilmente l'approccio per mostrare diff, forza aggiornamenti o fare qualsiasi altra cosa che ti piace.

Problemi correlati