Domanda

Stiamo usando Subversion, (la domanda potrebbe essere applicabile a molti sistemi di controllo della versione, ma Subversion è quello a cui tengo davvero.)

Il layout del nostro repository è simile al seguente:

(Layout A)

Web
  branches
  tags
  trunk
Libraries
  Foo
    branches
    tags
    trunk
  Bar
    branches
    tags
    trunk
WindowsClient
  branches
  tags
  trunk
DB
  branches
  tags
  trunk

Il problema è che l'unità di controllo delle versioni non è uguale all'unità di sviluppo - devo ottenere più checkout per ottenere un artefatto costruibile, e quando ramifico, devo ramificare più componenti (e fare il check-in in più posti).

Ciò implica che potremmo invece spostarci in una struttura come questa:

(Layout B)

Web
  branches
  tags
  trunk
    main
    libs
      Foo
      Bar
    DB
WindowsClient
  branches
  tags
  trunk
    main
    libs
      Foo
      Baz
    DB

Ma poi abbiamo copie duplicate di qualsiasi libreria condivisa. Potremmo mappare le librerie condivise usando svn: externals, ma questa è solo un'illusione: non si ramificheranno quando il progetto contenente lo è.

Un'ultima opzione è questa:

(Layout C)

branches
tags
trunk
  Web
  Libraries
    Foo
    Bar
  WindowsClient
  DB

Questo assicura che le biblioteche siano ramificate insieme al loro progetto di contenimento, ma a costo che l'unità di ramificazione è il mondo intero. (Ciò implica anche che l'unità di cassa è il mondo intero, il che è anche noioso.)

Quello che voglio è un layout del repository (Layout D) che mi consente di:

  • Diramazione di un progetto e delle sue librerie dipendenti contemporaneamente
  • Condividi librerie tra progetti

Sarebbe bello se potessi dare un'occhiata al progetto e alle sue librerie in un unico checkout, ma non è così importante come sopra.

Quindi la domanda è:

Esiste un layout D, cos'è e come si usa?

Modifica: Dal momento che sembra che non ci sia un layout di base che mi dia queste proprietà, sarei molto interessato a una sorta di funzione hook per portarmi lì. Sarebbe particolarmente bello se funzionasse con il client TortoiseSVN (Windows GUI), poiché è quello che stiamo usando.

È stato utile?

Soluzione

Vai con l'opzione C, quindi esegui i tuoi checkout in questo modo:

svn co -N ...../branches/mybranch workingcopy
cd workingcopy
svn update Web Libraries

Ora, quando si eseguono operazioni svn (incluso un semplice " svn update "), si occuperanno solo delle librerie Web e directory.

Leggi anche su directory sparse .

Altri suggerimenti

Non c'è una buona risposta alla domanda di "come strutturare il mio repository per questo flusso di lavoro?" perché il software non lo supporta davvero. Suggerirei di andare con il tuo layout B, ramificare il codice della libreria e passare il svn: external pertinente a quel ramo come necessario, o immediatamente se i tuoi rami devono fare riferimento a una versione off-trunk della biblioteca.

Stavo per suggerire che Git lo gestisse meglio, ma non è molto. Dato che i suoi sottomoduli si riferiscono a repository separati leggermente diversi dagli esterni e ogni copia del repository è un "ramo", ciò potrebbe rappresentare un leggero miglioramento.

  

Potremmo mappare le librerie condivise in uso   svn: esterni, ma questo è solo un   illusione - Non saranno ramificati   quando il progetto contenente è.

In realtà, saranno ramificati se si trovano nello stesso repository e hai utilizzato la relativa sintassi esterna, ad es. ^ \ mylib \ tronco . Tali riferimenti esterni vengono cambiati in cartelle normali (copiate). Devi esplicitamente passare --ignore-externals a svn copy per sopprimere questo comportamento, altrimenti finirai con copie come nel layout B. ( modifica : ero abbastanza sicuro che funzionasse in questo modo ma non riesco a riprodurre quel comportamento. Devo essermi sbagliato, scusa!)

Il fatto che gli esterni non si ramifichino sempre automaticamente non deve essere un problema. Vorrei utilizzare il layout B costruito con svn: externals (non copie), dirama il progetto (con --ignore-externals ), quindi dopo la diramazione adatta svn: externals in modo che punti al rami della libreria corretti.

Puoi impostare gli esterni in modo che puntino a una revisione specifica (buono per un controllo rigoroso; decidi quando passare a una nuova revisione di lbrary) o semplicemente segui HEAD (buono per l'integrazione continua, supponendo che tu abbia un build server impostato).

Il modo in cui l'abbiamo risolto è per le librerie esterne condivise utilizzate da diversi progetti, la libreria condivisa va nel proprio repository con il proprio trunk / rami / tag.

Abbiamo quindi un build server che pubblica e pubblica build di integrazione, pietre miliari e rilasci e l'artefatto binario viene copiato in un percorso condiviso e archiviato in directory specifiche della versione (di cui viene eseguito il backup).

Parte dello script di compilazione per un progetto dipendente (normalmente eseguito su richiesta come init / update anziché come parte di una build standard) quindi verifica la presenza di nuove versioni e acquisisce il file binario. Ciò ha il vantaggio di un versioning coerente del manufatto condiviso tra progetti dipendenti e riduce i tempi di costruzione in quanto tutti i progetti dipendenti possono condividere la stessa versione.

Per aiutare con il controllo delle versioni attualmente utilizziamo Apache Ivy che supporta cose come le dipendenze transitorie (es. recupero delle dipendenze di una dipendenza) e vincoli di versione (ad esempio questo progetto dovrebbe usare solo Foo versione 1.2. *).

Suggerirei che è il tuo approccio a queste librerie a causare i tuoi problemi. Puoi cambiarlo se inizi a pensare alle biblioteche come a progetti separati. Pensali come se avessero le loro ragioni per essere, il loro design e i loro cicli di rilascio, proprio come le librerie di terze parti che puoi usare per test unitari, lettori xml, accesso db, ecc.

Ovviamente avrai spesso momenti in cui una funzione in un progetto richiede una nuova funzione in una libreria. L'implementazione della funzione di libreria e l'utilizzo della funzione di libreria sono due attività indipendenti: possono essere un'attività aziendale ma due attività di sviluppo. Non è necessario collegare strettamente le due attività solo perché è così che è arrivato il lavoro. Controlla la libreria, modificala, rilasciala, quindi controlla il tuo progetto e usa la nuova versione della libreria nel tuo progetto.

Sono fermamente convinto che avere librerie separate nei loro trunk sia una buona cosa - non lo sopporto quando vedo più progetti rilasciabili in modo indipendente in un unico trunk. Ha un design scadente ed è stato supportato in un angolo dallo sviluppo di sviluppo. Ma per separarli devi essere in grado di rilasciare ogni progetto in modo indipendente - per me, questo è ciò che significa avere più progetti . Ma non è una cosa difficile da fare:

In primo luogo un progetto utilizza gli esterni per fare riferimento a una versione rilasciata specifica di una libreria. Questo è l'unico modo in cui un progetto fa riferimento a una biblioteca. Ciò significa che gli sviluppatori possono creare una nuova versione della libreria senza interrompere nessuno dei progetti che la utilizzano, poiché tutti i progetti faranno riferimento alla versione precedente. I progetti riescono a controllare quando vogliono introdurre nuove versioni delle librerie: gli sviluppatori possono scegliere quando vogliono impegnarsi a testare il loro codice con la nuova versione e quando occuparsi di risolvere eventuali problemi di build della nuova libreria introduce.

Quando modifichi esplicitamente versioni di una libreria come questa, ricevi anche una voce nel tuo progetto che dice " Ora sto usando questa versione della libreria X " ;, che ti dà una buona senso della storia nel tuo progetto su quando le cose funzionavano ed esattamente quando le cose sono cambiate.

Ora, ovviamente, tutto è bello in teoria, ma in pratica gli sviluppatori dovranno talvolta fare riferimento a versioni instabili e incompiute di una libreria. Va bene: uno sviluppatore può sempre cambiare la propria copia di lavoro in modo che punti al trunk della libreria anziché a un tag o a un ramo di sviluppo e utilizzi il codice da lì (anche se ci lavora su di esso se necessario, brrr). Uno switch è solo una modifica locale, quindi non avrà alcun effetto sul codice di commit. Se lo sviluppo del progetto si trova su un ramo instabile, puoi decidere di rendere lo switch più permanente modificando il riferimento esterno fino a quando il ramo non è pronto per essere reintegrato, ma questo non è qualcosa che normalmente verrebbe fatto senza un motivo esplicito.

E, infine, ramificare e taggare il tuo progetto diventa un semplice caso di creare un ramo o un tag del tuo progetto principale - tutto qui. Non è necessario preoccuparsi di ramificare le librerie: si prendono cura di se stessi. Il processo di modifica di una libreria non cambia se il progetto si trova nel trunk, in un ramo di sviluppo o in una versione di manutenzione. E le tue librerie possono esse stesse avere rami di sviluppo completamente indipendenti dai progetti principali, oltre a più versioni supportate, ecc., Fino a qualsiasi livello di complessità sia necessario e in grado di supportare.

Usando gli esterni sul tuo trunk o ramo di sviluppo, puoi avere un unico checkout che costruisce il tuo spazio di lavoro in qualunque struttura ti serva. Poiché tutte le librerie si trovano nella radice principale, puoi avere più checkout di più versioni senza ottenere scontri nella build.

Ho scoperto che questo sistema funziona abbastanza bene, e dopo aver spostato i lavori in un posto che non funziona in questo modo, mi ritrovo a desiderare il modo di lavorare precedente. Ci sono problemi, principalmente a che fare con le biblioteche a seconda delle biblioteche e se avere o meno esterni ricorsivi. La mia opinione è quella di diventare ricorsivo a meno che non causi un problema (o dolore eccessivo), quindi passare a un modello "degenerato" in cui il progetto deve conoscere certe dipendenze "profonde" anche se non le utilizza direttamente. Inoltre, decidi dove mettere le definizioni degli esterni e attenersi ad esso, nulla è più fastidioso della ricerca di quelle svn: proprietà esterne su cartelle casuali in diversi progetti. Metterli sulla radice del tronco va bene.

Questo è un problema difficile che non ha una buona soluzione economica; la soluzione di fascia alta è usare un & # 8220; linee di prodotti software & # 8221; sistema di gestione (ad es. pure :: varianti ). Tuttavia, la maggior parte di noi non riesce a spendere quella corrispondenza su un sistema di controllo del codice sorgente.

Pertanto andrei con LayoutA & # 8211; con ciascuna libreria gestita separatamente. Tenderei comunque a mettere & # 8220; trunk & # 8221; sotto & # 8220; rami & # 8221; in quanto è un ramo e mi piace avere tutti i rami alla stessa distanza dall'alto.

Il passaggio successivo dipende piuttosto dal sistema di compilazione, suppongo che Visual Studio qui.

  • Nella radice dell'albero di ogni ramo del prodotto
  • Crea un file bat che definisce una variabile di ambiente che contiene il nome del ramo di ciascuna libreria che desideri utilizzare
  • Modifica i file di progetto di Visual Studio per fare riferimento alle librerie utilizzando queste variabili di ambiente
  • Esegui il file batch dal prompt dei comandi di Visual Studio prima di avviare Visual Studio

Puoi anche cercare di scrivere un file MSBuild personalizzato piuttosto che usare un file batch. O scrivendo uno strumento che modifica tutti i file di progetto quando si cambia la versione di una libreria.

Se hai solo 1 o 2 librerie condivise e queste vengono modificate per un solo prodotto alla volta, .e.g. per aggiungere nuovi metodi per il progetto su cui si sta lavorando ora. Vorrei prendere in considerazione un ramo diverso della libreria per ciascun progetto e utilizzare il merge tacking SVN 1.5 per tenere traccia di ciò che sta succedendo. (Quando le modifiche sono stabili, unire il camion, quindi fondere dal camion a ciascun ramo dei progetti quando necessario)

(Se hai centinaia di librerie, devi tenere traccia della versione delle streghe di ogni libreria che ha bisogno l'una dell'altra. Questo inizia a diventare molto complesso!)

Non mi piace svn: external, in quanto non è chiaro dal file system sul tuo PC locale cosa sta succedendo. Comunque svn: external è una soluzione praticabile.

Avendo attraversato un problema simile, conosco il tuo dolore. È un problema difficile gestire le dipendenze in un repository con componenti gerarchiche.

Il nostro progetto prevedeva diversi prodotti (qualunque cosa spediate ai clienti) costituiti da vari componenti (molti dei quali condivisi). Avevamo ogni componente con la sua trilogia tags / branch / trunk , proprio come il tuo layout A (che è dopo tutto il modo consigliato).

Abbiamo usato svn: externals per fornire un modo per ogni prodotto di specificare componenti dipendenti (e sottocomponenti, ecc.), e inizialmente ha funzionato abbastanza bene. Ma alla fine ci siamo imbattuti in problemi, come ad esempio cosa succede quando si ramifica, cosa succede se un prodotto deve bloccare una depdency a una certa revisione, come propagare i tag attraverso gli esterni per la gestione della configurazione (in modo da poter effettivamente ricostruire lo stesso albero!) , e così via. Quindi svn: externals risolve alcuni problemi ma ne introduce altri.

Ho finito per scrivere alcuni script per gestirlo, ma era ancora un po 'contorto. Fortunatamente, puoi usare i collegamenti Python-Subversion per scrivere app Python per manipolare le proprietà, così puoi fare cose come far propagare i tag attraverso componenti dipendenti e così via.

Esiste un progetto progettato per affrontare questo problema dei moduli dipendenti, chiamato Piston . Sembra uno strumento molto carino e generico proprio per questo tipo di problema. Non l'ho distribuito in produzione, ma al momento sembrava che avrebbe fatto la maggior parte di ciò di cui avevamo bisogno. E certamente sembra una soluzione più flessibile di quella fornita dagli esterni (che è ancora un processo molto manuale).

In conclusione: potresti rimanere fedele al Layout A e usare Piston per gestire le dipendenze in modo che tutte le versioni giuste delle tue librerie vengano assemblate nella tua directory di lavoro.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top