Git e dipendenze del progetto
Nicola Paolucci
Developer Advocate
Rifletti sulle domande seguenti:
Come gestisci le dipendenze del progetto con git
?
Il nostro progetto è composto da più repository interdipendenti. Attualmente li gestiamo con svn:externals
. Qual è il modo migliore per gestirli con git
?
Come si divide un repository molto grande in componenti più piccoli usando git
?
Queste sono alcune delle nostre domande più frequenti.
Questo argomento sembra essere una nota dolente per molti team software che adottano git
, quindi in questo articolo cercherò di far luce sulla questione.
Ovviamente le dipendenze del progetto e l'infrastruttura di compilazione sono due aree interconnesse, e anche all'interno di Atlassian si è scatenata una discussione sul "futuro delle compilazioni".
Avere repository separati invece di averne uno solo può complicare alcune cose. Ma è un passaggio relativamente naturale, a volte obbligatorio, dell'evoluzione di un progetto software per almeno due motivi principali: aumento dei tempi di compilazione e dipendenze condivise tra i progetti.
Rapida panoramica delle linee guida e delle soluzioni subottimali
Quindi torniamo alla domanda: come si monitorano e gestiscono le dipendenze del progetto con git
?
Se possibile, non si fa!
Scherzi a parte, rispondo a questa domanda dapprima a grandi linee per poi approfondire l'argomento. Innanzitutto, prendiamo atto del fatto che non esiste una soluzione ottimale, in git
o in altre soluzioni, che risolva in modo indolore tutti i problemi legati alle dipendenze dei progetti.
Una volta che un progetto supera una certa dimensione, ha senso suddividerlo in componenti logici, ma non aspettare di avere più di 100 milioni di righe di codice in un unico repository per farlo. Le seguenti sono solo delle linee guida che ti aiuteranno ad elaborare il tuo personale approccio.
materiale correlato
Installa Git
Scopri la soluzione
Impara a utilizzare Git con Bitbucket Cloud
Prima scelta: uso di uno strumento di compilazione/per le dipendenze appropriato al posto di git
Gli strumenti di gestione delle dipendenze sono il metodo che attualmente consiglio per gestire le difficoltà e i tempi di compilazione in costante aumento dei progetti di grandi dimensioni.
Mantieni i moduli separati in repository individuali e gestisci la loro interdipendenza con uno strumento creato appositamente. C'è uno strumento per (quasi) tutti gli stack tecnologici esistenti. Ecco alcuni esempi:
- Maven (o Gradle) se usi Java
- Npm per le app Node
- Bower, Component.io ecc. se usi Javascript (aggiornato!)
- Pip e requirements.txt se usi Python
- RubyGems, Bundler se usi Ruby
- NuGet per .NET
- Ivy (o delle azioni CMake personalizzate) per C++ (aggiornato!)
- CocoaPods per le app Cocoa iOS
- Composier o Phing per PHP (aggiunto!)
- In Go l'infrastruttura di compilazione/delle dipendenze è in qualche modo integrata nel linguaggio, anche se si sta lavorando a una soluzione più completa (vedi godep). Per il nostro server Git, (Bitbucket) utilizziamo sia Maven che Bower. In fase di compilazione, lo strumento selezionato esegue un pull delle versioni corrette delle dipendenze per consentire la compilazione del progetto principale. Alcuni di questi strumenti presentano dei limiti e formulano ipotesi non ottimali, tuttavia sono comprovati e validi.
Le difficoltà di suddivisione del progetto
In parole semplici, all'inizio di un progetto tutto è racchiuso in un'unica build. Ma, man mano che il progetto cresce, la build potrebbe diventare troppo lenta e a quel punto diventa necessaria la memorizzazione nella cache. È qui che entra in gioco la gestione delle dipendenze. Questo, a proposito, implica che i sottomoduli (vedi sotto) si prestano molto bene ai linguaggi dinamici, ad esempio. Fondamentalmente, penso che la maggior parte di noi prima o poi debba occuparsi dei tempi di compilazione, motivo per cui è importante usare uno strumento di gestione delle dipendenze.
La suddivisione dei componenti in repository separati comporta delle serie difficoltà. In ordine sparso:
- Per apportare modifiche a un componente è necessario un rilascio
- L'operazione richiede tempo e può non andare a buon fine per molte ragioni banali
- Sembra un'operazione inutile da eseguire per le piccole modifiche
- Richiede la configurazione manuale di nuove build per ogni componente
- Ostacola la rilevabilità dei repository
- Richiede il refactoring quando non tutta l'origine è disponibile in un unico repository
- In alcune configurazioni (come la nostra) l'aggiornamento delle API richiede un rilascio milestone del prodotto, quindi del plugin e poi ancora del prodotto. Forse ho saltato alcune cose, ma credo di aver reso il concetto. La soluzione perfetta al problema è tutt'altro che questa.
Seconda scelta: uso dei sottomoduli git
Se non puoi o non vuoi usare uno strumento per le dipendenze, git
offre una funzione per la gestione dei sottomoduli (submodules
). I sottomoduli possono essere pratici, soprattutto per i linguaggi dinamici. Tuttavia, non è detto che saranno necessariamente in grado di farti evitare i tempi di compilazione lenti. Ho già scritto alcune linee guida e suggerimenti a riguardo e ho anche esplorato delle alternative. Anche su Internet in generale si possono trovare molti argomenti contro il loro utilizzo.
Corrispondenza diretta tra svn:external e git
MA! Se cerchi una corrispondenza diretta tra svn:externals
e git
, è consigliabile usare i sottomoduli (submodules
assicurandoti che i submodules
tengano traccia solo dei branch di rilascio e non dei commit casuali.
Terza scelta: uso di altri strumenti di compilazione e per le dipendenze tra stack
Non sempre ti ritroverai a lavorare a un progetto completamente uniforme e che può essere compilato e assemblato con un solo strumento. Ad esempio, alcuni progetti mobili dovranno gestire le dipendenze Java e C++ o utilizzare strumenti proprietari per generare risorse. Per queste situazioni più complesse, puoi potenziare Git
aggiungendo un ulteriore livello. Un ottimo esempio in questo caso è il repository di Android.
Altri strumenti di compilazione degni di nota:
Conclusioni e letture aggiuntive
Suggerimenti per ulteriori letture sull'argomento delle infrastrutture di costruzione (e Maven) di Charles O'Farrell:
- Alla ricerca dello strumento di compilazione definitivo
- E il seguito: Criticità della progettazione di Maven
- Maven ricorsivo considerato dannoso
Vorrei concludere con questa eccellente citazione tratta dall'ultimo articolo riportato sopra. Anche se riguarda Maven, potrebbe applicarsi ugualmente ad altri strumenti di compilazione e per le dipendenze:
"La cache non fa altro che velocizzare le cose. Si potrebbe rimuovere completamente la cache e il sistema circostante funzionerebbe allo stesso modo, solo più lentamente. Inoltre, la cache non ha effetti collaterali. Indipendentemente da come si è utilizzata la cache in passato, una determinata query nella cache restituirà lo stesso valore per la stessa query in futuro.
L'esperienza offerta da Maven è molto diversa da quella descritta! I repository Maven vengono usati come cache, ma senza le proprietà della cache. Quando si effettua una query in un repository Maven, le operazioni svolte in precedenza hanno grande importanza. Viene restituito l'elemento inserito più di recente e la query può persino non andare a buon fine se fa riferimento a un elemento non ancora inserito nel repository".
Condividi l'articolo
Argomento successivo
Letture consigliate
Aggiungi ai preferiti queste risorse per ricevere informazioni sui tipi di team DevOps e aggiornamenti continui su DevOps in Atlassian.