Scegli tra progetti singoli o multipli in un repository git?


223

In un gitambiente in cui abbiamo modularizzato la maggior parte dei progetti, stiamo affrontando il problema di un progetto per repository o di più progetti per repository . Consideriamo un progetto modulare:

myProject/
   +-- gui
   +-- core
   +-- api
   +-- implA
   +-- implB

Oggi abbiamo un progetto per repository . Dà libertà a

  • release singoli componenti
  • tag singoli componenti

Ma è anche ingombrante per i branchcomponenti poiché spesso la ramificazione apirichiede rami equivalenti coree forse altri componenti.

Dato che vogliamo releasesingoli componenti, possiamo ancora ottenere la stessa flessibilità utilizzando un progetto multiplo per progettazione del repository .

Quali esperienze ci sono e come / perché hai affrontato questi problemi?


1
Ho un problema molto simile in questo momento. Devo rilasciare diverse versioni di un progetto, quindi dovranno trovarsi in repository diversi. Questo è un incubo da gestire però. Sarebbe bello se ci fosse un modo per ramificare solo le sottodirectory.
Andrew T Finnell,

1
Ogni modulo deve avere numeri di versione separati. E usiamo git-describe.
Linquize,



Sono sorpreso di vedere che Bit ( bitsrc.io ) e Lerna ( github.com/lerna/lerna ) non sono menzionati! Puoi saperne di più qui: hackernoon.com/…
Yoni

Risposte:


199

Ci sono tre principali svantaggi one project per repositorynel modo in cui l'hai descritta sopra. Questi sono meno veri se si tratta di progetti veramente distinti, ma dai suoni che ne derivano a uno spesso richiedono cambiamenti a un altro, il che può davvero esagerare questi problemi:

  1. È più difficile scoprire quando sono stati introdotti i bug. Strumenti come git bisectdiventano molto più difficili da usare quando si frattura il repository in sotto-repository. È possibile, non è così semplice, il che significa che la caccia ai bug in tempi di crisi è molto più difficile.
  2. Tracciare l'intera cronologia di una funzione è molto più difficile. Comandi che attraversano la cronologia come git logsemplicemente non generano la cronologia in modo significativo con strutture di repository fratturate. È possibile ottenere un output utile con sottomoduli o sottotitoli o tramite altri metodi di script, ma non è lo stesso della digitazione tig --grep=<caseID>o della git log --grep=<caseID>scansione di tutti i commit che ti interessano. La tua storia diventa più difficile da capire, il che la rende meno utile quando ne hai davvero bisogno.
  3. I nuovi sviluppatori dedicano più tempo all'apprendimento della struttura del controllo versione prima di poter iniziare a scrivere codice. Ogni nuovo lavoro richiede procedure di prelievo, ma la fratturazione di un repository di progetto significa che devono raccogliere la struttura VC oltre all'architettura del codice. Nella mia esperienza, questo è particolarmente difficile per gli sviluppatori che non conoscono chi proviene da negozi più tradizionali e centralizzati che utilizzano un unico repository.

Alla fine, è un calcolo del costo opportunità. In un ex datore di lavoro, la nostra domanda principale era divisa in 35 diversi sotto-repository. Inoltre, abbiamo usato un insieme complicato di script per cercare la cronologia, assicurandoci che lo stato (ovvero i rami di produzione e di sviluppo) fosse lo stesso su di essi e li abbiamo distribuiti individualmente o in massa.

Era veramente troppo; troppo per noi almeno. Il sovraccarico di gestione ha reso le nostre funzioni meno agili, ha reso le implementazioni molto più difficili, ha reso l'insegnamento di nuovi sviluppatori richiedere troppo tempo e, alla fine, abbiamo potuto a malapena ricordare perché abbiamo fratturato il repository in primo luogo. Un bellissimo giorno di primavera, ho speso $ 10 per un pomeriggio di tempo di calcolo dei cluster in EC2. Ho ricomposto i repository insieme a un paio di dozzine di git filter-branchchiamate. Non abbiamo mai guardato indietro.


7
A parte l'argomento, ci sono poche cose più piacevoli come gestore di repository rispetto all'acquisto di tempo su un sistema che può fare in due ore ciò che il tuo laptop non potrebbe fare in 20, a meno del prezzo del pranzo. A volte amo davvero Internet.
Christopher,

2
Come rilasceresti quei singoli progetti come versioni separate? O non hai mai bisogno di farlo? Questo è il problema che ho. Con se è necessario creare un V1 del Progetto A e un V2 del Progetto B.
Andrew T Finnell,

5
Per muoversi tra il "un progetto per pronti contro termine" e "più pronti contro termine" considerare git-sottostruttura (buona spiegazione a stackoverflow.com/a/17864475/15585 )
deterb

1
Ho scritto una sceneggiatura per automatizzare questo caso per casi d'uso comuni: github.com/Oakleon/git-join-repos
chrishiestand,

Che cos'è una "struttura VC?"
Robert Harvey,

60

Christopher ha fatto un ottimo lavoro nell'enumerare gli svantaggi di un modello a progetto singolo per repository. Vorrei discutere alcuni dei motivi per cui potresti prendere in considerazione un approccio a più repository. In molti ambienti in cui ho lavorato, un approccio multi-repository è stato una soluzione ragionevole, ma la decisione di quanti repository avere e dove effettuare i tagli non è sempre stata facile da realizzare.

Nella mia attuale posizione, ho migrato un repository CVS a singolo repository con oltre dieci anni di storia in una serie di repository git. Da quella decisione iniziale, il numero di repository è cresciuto (attraverso le azioni di altre squadre), al punto che sospetto che abbiamo più di quanto sarebbe ottimale. Alcuni neoassunti hanno suggerito di fondere i repository ma ho discusso contro di esso. Il progetto Wayland ha un'esperienza simile. In un discorso che ho visto di recente, avevano, ad un certo punto, oltre 200 repository git, per i quali il responsabile si è scusato. Guardando il loro sito web , ora vedo che sono in 5, il che sembra ragionevole. È importante osservare che unire e dividere i repository è un compito gestibile ed è bene sperimentare (entro limiti ragionevoli).

Quindi, quando potresti volere più repository?

  1. Un singolo repository sarebbe troppo grande per essere efficiente.
  2. I tuoi repository sono liberamente accoppiati o disaccoppiati.
  3. Uno sviluppatore in genere ha bisogno solo di uno o di un piccolo sottoinsieme dei repository per svilupparlo.
  4. In genere si desidera sviluppare i repository in modo indipendente e è necessario sincronizzarli solo occasionalmente.
  5. Vuoi incoraggiare una maggiore modularità.
  6. Diversi team lavorano su diversi repository.

I punti 2 e 3 sono significativi solo se vale il punto 1. Dividendo i nostri repository, ho significativamente ridotto i ritardi subiti dai nostri colleghi fuori sede, ridotto il consumo del disco e migliorato il traffico di rete.

4 e 5 sono più sottili. Quando si dividono i repository di dire un client e un server, ciò rende più costoso coordinare le modifiche tra il codice client e il server. Questo può essere positivo, in quanto incoraggia un'interfaccia disaccoppiata tra i due.

Anche con i lati negativi dei progetti multi-repository, in questo modo viene svolto molto lavoro rispettabile: wayland e boost vengono in mente. Non credo che si sia ancora sviluppato un consenso in merito alle migliori pratiche e è necessario un certo giudizio. Gli strumenti per lavorare con più repository (git-subtree, git-submodule e altri) sono ancora in fase di sviluppo e sperimentazione. Il mio consiglio è di sperimentare ed essere pragmatico.


7
Questa risposta sarebbe ancora più utile con un riferimento a supporto dell'affermazione: "unire e dividere i repository è un compito gestibile".
Wildcard il

3
I repository multipli possono anche funzionare contro la modularità perché rendono più difficile la modifica del codice condiviso. Le dipendenze cross-repo rendono più difficile l'integrazione, possono rompere il codice più facilmente (anche se si dispone di buoni strumenti per verificarlo) e la minaccia di rompere il codice out-of-repo scoraggia le interfacce di refactoring, che è uno dei tuoi strumenti più potenti per rendere le cose più modulare.
Curt J. Sampson,

Tutto ciò che riguarda MicroServices e il design DDD è valido qui. È necessario ridurre al minimo il codice condiviso.
Arwin,

49

Mentre usiamo GitHub, in realtà abbiamo più progetti in un unico repository ma assicuriamo che quei progetti / moduli siano opportunamente modularizzati (usiamo -api e -core convenzioni + Maven + controllo statico e di runtime e potremmo anche andare a OSGi un giorno per l'avvio) .

Cosa risparmia? Bene, non dobbiamo emettere più richieste pull se stiamo cambiando qualcosa di piccolo in più progetti. Problemi e Wiki sono mantenuti centralizzati ecc.

Trattiamo ancora ogni modulo / progetto come un progetto indipendente adeguato e li costruiamo e li integriamo separatamente nel nostro server CI ecc.


1
Molto interessante. Sospetto che questo sia un modello comune su Github. Se si affrontano rilasci di singoli componenti, si impiega qualcosa di simile submoduleso si rilascia / tag l'intero repository?
Johan Sjöberg,

sottomoduli se dobbiamo, ma per ora abbiamo la versione dal genitore verso il basso.
Martijn Verburg,

Al mio attuale datore di lavoro utilizziamo una strategia simile e raggruppiamo i metadati relativi al commit più recente in un progetto nei vari file manifest di artefatti (ovvero i risultati di git log -1 -- <project_dir>). È davvero fantastico. Questa risposta merita più voti.
Christopher,

22

Per me, la principale differenza nell'uso di uno o più di un repository sono le risposte alle seguenti domande:

  • Le parti multiple sono sviluppate dallo stesso team, hanno lo stesso ciclo di rilascio, lo stesso cliente? Quindi ci sono meno motivi per dividere il repository.
  • Le parti multiple dipendono fortemente l'una dall'altra? Quindi la suddivisione del modello, del controller e dell'interfaccia utente (anche quando sono parti diverse) non è molto sensibile, a causa dell'alta dipendenza reciproca. Ma se 2 parti hanno solo una piccola dipendenza, che viene implementata da un'interfaccia stabile che viene cambiata solo ogni pochi anni, quindi sarebbe saggio dividere le 2 parti in 2 repository.

Ad esempio, ho una piccola applicazione (solo client), che controlla la "qualità" di un repository Subversion. C'è l'implementazione di base, che potrebbe essere avviata dalla riga di comando e funziona bene con Java 6. Ma ho iniziato a implementare un'interfaccia utente, che utilizza JavaFX come parte di Java 8. Quindi ho diviso il 2 e creato un secondo repository (con un secondo processo di compilazione), con diversa pianificazione, ...

Mi piacciono le risposte sopra (votate), ma penso che non siano l'intera storia vera. Quindi volevo aggiungere anche gli argomenti per dividere i repository. Quindi la vera risposta (quando dividere) potrebbe essere da qualche parte nel mezzo ...



0

Dal tuo esempio, i repository dovrebbero essere configurati in termini di interdipendenza. Qui si applicano tutti i ragionamenti sulla progettazione di MicroServices e Domain Driven Design: in alcuni casi il codice duplicato è accettabile, funziona con le interfacce, non rompere la compatibilità a meno che non sia necessario, ecc.

A mio avviso, un'interfaccia utente dovrebbe essere indipendente dal back-end. Quindi un repository di progetti di interfaccia utente dovrebbe in genere contenere il codice UI e il controller client. Il controller client si connetterà con i controller del servizio in modo astratto. Utilizzeranno un'astrazione client / api di servizio che viene gestita separatamente dal servizio, in modo che un servizio possa essere aggiornato senza interrompere i client (potrebbero esserci diversi client).

Quindi un servizio stesso dovrebbe essere il proprio repository. Dal mio punto di vista, il servizio è solo un involucro di alcune logiche di business a singolo punto di verità. Pertanto, la logica aziendale dovrebbe in genere essere separata dalla tecnologia di servizio che la ospita. D'altra parte, l'implementazione del repository è in genere così strettamente connessa alla logica aziendale, che potrebbe essere integrata nello stesso repository. Ma anche lì il tuo chilometraggio può variare.

Naturalmente, i progetti semplici che difficilmente cambieranno molto in termini di tecnologia o supporto di più stack, in cui tutta l'interfaccia utente può essere ospitata dalla stessa fonte del back-end e i servizi di back-end sono in genere utilizzati solo dallo stesso client, possono beneficiare di più repository strettamente integrati.

In tal caso, probabilmente staresti bene solo con la verticale completa in un repository e ti concentrerai solo sull'assicurarti che i tuoi domini funzionali siano correttamente autonomi nel loro repository. Avrai quindi ancora la maggior parte dei vantaggi dei repository più piccoli, e altrimenti un piccolo overhead.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.