Continui lo sviluppo in un ramo o nel tronco? [chiuso]


170

Supponiamo di sviluppare un prodotto software con rilasci periodici. Quali sono le migliori pratiche in materia di diramazione e fusione? Tagliare le filiali di rilascio periodico al pubblico (o chiunque sia il tuo cliente) e quindi continuare lo sviluppo sul trunk, o considerare il trunk come versione stabile, etichettarlo periodicamente come rilascio e fare il tuo lavoro sperimentale nei rami. Cosa pensa la gente è il tronco considerato "oro" o considerato un "sand box"?


3
Ti chiedi se questo può essere ricodificato senza svn in quanto è abbastanza generico per la gestione del controllo del codice sorgente?
Scott Saad,

4
Questa sembra essere una di quelle domande "religiose".
James McMahon,

@James McMahon - è più che ci sono davvero due buone pratiche reciprocamente esclusive, ma alcune persone pensano che ce ne sia solo una. Non aiuta il fatto che SO vuole che tu abbia una risposta corretta.
Ken Liu,

Risposte:


151

Ho provato entrambi i metodi con una grande applicazione commerciale.

La risposta a quale metodo è migliore dipende fortemente dalla tua situazione esatta, ma scriverò ciò che la mia esperienza complessiva ha dimostrato finora.

Il metodo migliore nel complesso (secondo la mia esperienza): il bagagliaio dovrebbe essere sempre stabile.

Ecco alcune linee guida e vantaggi di questo metodo:

  • Codifica ogni attività (o set correlato di attività) nel proprio ramo, quindi avrai la flessibilità di quando desideri unire queste attività ed eseguire una versione.
  • Il controllo qualità deve essere eseguito su ciascun ramo prima di essere unito al trunk.
  • Eseguendo il QA su ogni singolo ramo, saprai esattamente cosa ha causato il bug più facilmente.
  • Questa soluzione si adatta a qualsiasi numero di sviluppatori.
  • Questo metodo funziona poiché la ramificazione è un'operazione quasi istantanea in SVN.
  • Tagga ogni versione che esegui.
  • È possibile sviluppare funzionalità che non si prevede di rilasciare per un po 'e decidere esattamente quando unirle.
  • Per tutto il lavoro che fai, puoi avere il vantaggio di impegnare il tuo codice. Se lavori solo fuori dal trunk, probabilmente manterrai il tuo codice senza impegno, e quindi non protetto e senza cronologia automatica.

Se provi a fare il contrario e fai tutto il tuo sviluppo nel trunk, avrai i seguenti problemi:

  • Problemi di build costanti per build quotidiane
  • Perdita di produttività quando uno sviluppatore commette un problema per tutte le altre persone nel progetto
  • Cicli di rilascio più lunghi, perché è necessario finalmente ottenere una versione stabile
  • Rilasci meno stabili

Semplicemente non avrai la flessibilità di cui hai bisogno se provi a mantenere un ramo stabile e il tronco come sandbox di sviluppo. Il motivo è che non puoi scegliere dal bagagliaio ciò che vuoi mettere in quella versione stabile. Sarebbe già tutto mescolato insieme nel bagagliaio.

L'unico caso in particolare che direi di fare tutto lo sviluppo nel bagagliaio è quando si avvia un nuovo progetto. Potrebbero esserci anche altri casi a seconda della situazione.


A proposito, i sistemi di controllo della versione distribuita offrono molta più flessibilità e consiglio vivamente di passare a hg o git.


35
Siamo spiacenti, ma questa risposta è sbagliata. Tutto lo sviluppo dovrebbe avvenire nel bagagliaio. Se hai qualcosa da "spike" o qualche funzione "rischiosa", crea un ramo di funzionalità. I rami dovrebbero essere mantenuti in manutenzione per ogni versione del prodotto in produzione, oppure se esiste una singola versione utilizzare un ramo di integrazione.
Mitch Wheat,

52
Non stavo sostenendo che questo era l'unico modo, solo che era il modo migliore. Ovviamente se pensi di avere abbastanza motivi per pensare che mi sbagli, allora dovresti pubblicarlo. Almeno la mia risposta è giustificata.
Brian R. Bondy,

5
Ciò è problematico, poiché gli sviluppatori possono lavorare a lungo su un ramo che si discosta dal trunk principale. L'integrazione di queste cose in seguito può produrre grossi mal di testa. Per me è stato sempre più facile mantenere un tronco di spurgo con alcuni requisiti minimi (deve sempre compilare) e ramificare le cose che dovrebbero essere stabilizzate per un rilascio.
Mnementh,

31
In risposta al post di Mnementh, credo che una buona soluzione sia che uno sviluppatore dovrebbe unire periodicamente il tronco nel proprio ramo in modo da non allontanarsi troppo dallo stato del tronco. Spetta a ciascuno sviluppatore farlo abbastanza spesso da non avere un forte mal di testa da reintegrazione in qualsiasi momento.
RjOllos,

8
@Mnementh non è una scusa. Le migliori pratiche e il buon senso dicono che tutti i membri del team dovrebbero aggiornare i loro rami con il tronco. Il trunk mainline non è pensato per essere perfetto né per essere ciò che spingi alla produzione, deve solo essere compilato ed è per questo che in buoni ambienti di sviluppo la maggior parte degli sviluppatori è molto brava a assicurarsi che ciò accada e, in caso contrario, il il team ha il diritto di concedere a quella persona un momento difficile ... anche strumenti come il controllo automatico della velocità e altre configurazioni di build continue. Ecco cos'è l'integrazione continua! Hai test di qualità per i tuoi rami e non il tuo tronco principale.
Positivo Acquista

66

Ho lavorato con entrambe le tecniche e direi che lo sviluppo sul tronco e la ramificazione di punti stabili come rilasci è il modo migliore per andare.

Quelle persone sopra che obiettano dicendo che avrai:

  • Problemi di build costanti per build quotidiane
  • Perdita di produttività quando uno sviluppatore commette un problema per tutte le altre persone nel progetto

probabilmente non hanno usato tecniche di integrazione continua.

È vero che se non esegui più build di test durante il giorno, diciamo una volta ogni ora circa, si lasceranno aperti a questi problemi che strozzeranno rapidamente il ritmo dello sviluppo.

Effettuare diverse build di test durante il giorno ripiega rapidamente gli aggiornamenti della base di codice principale in modo che altri possano usarla e ti avvisa anche durante il giorno se qualcuno ha rotto la build in modo che possano risolverla prima di andare a casa.

Come sottolineato, scoprire una build fallita solo quando la build notturna per l'esecuzione dei test di regressione fallisce è pura follia e rallenterà rapidamente le cose.

Leggi l'articolo di Martin Fowler sull'integrazione continua . Abbiamo implementato il nostro sistema per un grande progetto (3.000 kSLOC) in circa 2.000 linee di Posix sh.


1
Che cosa ha a che fare con "l'integrazione continua" con la probabilità che un team sia in ritardo sulla funzionalità e ritardi un intero ciclo di rilascio? È il modo migliore per andare "per te"! Fare più build al giorno non risolve alcun potenziale problema se non sai che costruisce! Le tue argomentazioni non forniscono la prova che sia un modo migliore (anche se di solito lo faccio anche io).
Jeach,

CI è necessario per questa risposta, ma anche per Brian.
jyoungdev,

2
@Jeach, fare più build al giorno ti dà la sicurezza che si costruisce in modo da poter eseguire test regolarmente, sia semplici test di fumo durante il giorno o test di regressione durante la sera. Se lasci la build fino alla build della sera per il test di regressione, puoi ripristinare l'intero progetto di un giorno solo perché non puoi costruirlo. Ciò significa che tutti gli sviluppatori non saranno in grado di vedere i risultati dei test di regressione per il nuovo codice che hanno inviato. Un costo piuttosto costoso, solo perché, ad esempio, qualcuno ha registrato il codice contenente un errore di sintassi.
Rob Wells,

cosa succede se una funzione richiede 2 mesi per essere costruita e un'altra richiede 6 mesi per essere costruita, devi usare le filiali lì, in questi casi non tutto può essere controllato nel trunk
Kalpesh Soni

1
@ Lupo stai confondendo la confusione con la confusione, la gente costruisce prodotti, non tutti lavorano per gli sviluppatori
Kalpesh Soni

36

Tendo ad adottare l'approccio "release branch". Il tronco è volatile. Una volta che il tempo di rilascio si avvicina, farei un ramo di rilascio, che tratterei con più cautela. Al termine, eticherei / taggerò lo stato del repository in modo da conoscere la versione rilasciata "ufficiale".

Capisco che ci sono altri modi per farlo - questo è solo il modo in cui l'ho fatto in passato.


19

Tutti e due.

Il tronco viene utilizzato per la maggior parte dello sviluppo. Ma si prevede che verranno fatti tutti gli sforzi possibili per garantire che qualsiasi check-in nel bagagliaio non lo rompa. (parzialmente verificato da un sistema automatizzato di costruzione e test)

I rilasci vengono mantenuti nella loro directory, con solo correzioni di bug (e poi uniti in trunk).

Qualsiasi nuova funzionalità che lascerà il trunk in uno stato instabile o non funzionante viene eseguita nel suo ramo separato e quindi unita al trunk al termine.


3
Sono con te su questo ... gli sviluppatori che si attengono a un solo metodo in ogni momento sono il problema!
Jeach,

14

Mi piace e utilizzo l'approccio descritto da Henrik Kniberg in Controllo versione per più team agili . Henrik ha fatto un ottimo lavoro nel spiegare come gestire il controllo della versione in un ambiente agile con più team (funziona anche per un singolo team in ambienti tradizionali) e non ha senso parafrasarlo, quindi posterò semplicemente il "cheat sheet" (che si spiega da sé) di seguito:

testo alternativo testo alternativo

Mi piace perché:

  • È semplice: puoi ottenerlo dall'immagine.
  • Funziona (e scala) bene senza troppi problemi di unione e conflitto.
  • È possibile rilasciare "software funzionante" in qualsiasi momento (nello spirito di agile).

E nel caso in cui non fosse abbastanza esplicito: lo sviluppo avviene in "rami di lavoro", il trunk viene utilizzato per il codice FATTO (rilasciabile). Controlla il controllo versione per più team agili per tutti i dettagli.


La mia esperienza personale è che questo funziona SOLO per piccoli team, a differenza del tuo commento "ridimensiona". Man mano che le squadre crescono e le storie vengono ridisegnate, tutte le altre squadre trascorrono considerevoli quantità di squadre a fare le fusioni. E su progetti molto grandi (molti file e KLOC), i problemi di unione iniziano a comparire regolarmente, soprattutto quando c'è molta volatilità del codice.
Jeach,

@Jeach Ha funzionato bene per noi su un grande progetto con 5 team organizzati in team di funzioni, anche se non sto negando che la fusione abbia un costo.
Pascal Thivent,

11

Un buon riferimento a un processo di sviluppo che mantiene stabile il bagagliaio e fa tutto il lavoro nei rami è il sistema di sviluppo della qualità suprema di Divmod . Un breve riassunto:

  • Tutto il lavoro svolto deve essere associato a un ticket
  • Viene creato un nuovo ramo per ogni ticket in cui viene svolto il lavoro per quel ticket
  • Le modifiche da quel ramo non vengono unite nuovamente nel trunk della linea principale senza essere riviste da un altro membro del progetto

Usano SVN per questo, ma questo potrebbe essere fatto facilmente con qualsiasi sistema di controllo della versione distribuita.


10

Penso che il tuo secondo approccio (es. Taggare le pubblicazioni e fare cose sperimentali nei rami, considerando il tronco stabile) sia l'approccio migliore.

Dovrebbe essere chiaro che i rami ereditano tutti i bug di un sistema nel momento in cui è ramificato: se le correzioni vengono applicate a un tronco, dovrai andare uno per uno a tutti i rami se mantieni i rami come una sorta di terminatore del ciclo di rilascio. Se hai già avuto 20 versioni e hai scoperto un bug che risale al primo, dovrai applicare nuovamente la correzione 20 volte.

Si suppone che i rami siano le vere scatole di sabbia, anche se il tronco dovrà svolgere anche questo ruolo: i tag indicheranno se il codice è "oro" in quel momento, adatto al rilascio.


8

Sviluppiamo sul bagagliaio a meno che i cambiamenti non siano troppo importanti, destabilizzanti o in procinto di essere in procinto di rilasciare un'importante versione di uno dei nostri prodotti, nel qual caso creiamo una filiale temporanea. Creiamo anche una filiale permanente per ogni singola release di prodotto. Ho trovato molto utile il documento di Microsoft su Branching Guidance . Anche il tutorial di Eric Sink sulla ramificazione è interessante e sottolinea che ciò che funziona per Microsoft potrebbe essere troppo pesante per alcuni di noi. È stato nel nostro caso, in realtà usiamo l'approccio che Eric dice che fa il suo team.


5

Dipende dalle tue situazioni. Usiamo Perforce e in genere abbiamo diverse linee di sviluppo. Il tronco è considerato "oro" e tutto lo sviluppo avviene su rami che si fondono nuovamente con la linea principale quando sono abbastanza stabili da integrarsi. Ciò consente il rifiuto di funzioni che non tagliano e che possono fornire nel tempo solide capacità incrementali che possono essere acquisite da progetti / funzionalità indipendenti.

C'è un costo di integrazione per la fusione e il recupero delle nuove funzionalità introdotte nel bagagliaio, ma soffrirai comunque questo dolore. Avere tutti insieme sul tronco può portare a una situazione del selvaggio west, mentre la ramificazione ti consente di scalare e scegliere i punti in cui ti piacerebbe prendere le amare pillole di integrazione. Al momento siamo ridimensionati a oltre un centinaio di sviluppatori su una dozzina di progetti, ognuno con più versioni che utilizzano gli stessi componenti principali e funziona abbastanza bene.

Il bello di questo è che puoi farlo in modo ricorsivo: un ramo di una grande caratteristica può essere il suo tronco con altri rami che se ne staccano. Inoltre, le versioni finali ottengono una nuova filiale per offrirti un posto dove eseguire una manutenzione stabile.


4

Tentare di gestire la manutenzione dell'attuale codice di produzione in linea con i nuovi sviluppi è nella migliore delle ipotesi problematico. Al fine di mitigare tali problemi, il codice dovrebbe diramarsi in una linea di manutenzione una volta completati gli sforzi di collaudo e il codice è pronto per la consegna. Inoltre, la linea principale dovrebbe essere diramata per aiutare nella stabilizzazione dei rilasci, per contenere sforzi di sviluppo sperimentale o per ospitare qualsiasi sforzo di sviluppo il cui ciclo di vita si estende su più rilasci.

Un ramo non di manutenzione dovrebbe essere creato solo quando esiste la probabilità (o certezza) di collisioni tra il codice che sarebbe difficile da gestire in altro modo. Se il ramo non risolve un problema logistico, ne creerà uno.

Lo sviluppo del rilascio normale si verifica nella linea principale. Gli sviluppatori effettuano il check-in e out della linea principale per il normale lavoro di rilascio. Il lavoro di sviluppo per le patch al codice di produzione corrente dovrebbe essere nel ramo per quella versione e quindi unito alla linea principale una volta che la patch ha superato il test e viene distribuita. Le attività svolte in settori non soggetti a manutenzione dovrebbero essere coordinate caso per caso.


4

Dipende dalle dimensioni del tuo sforzo di sviluppo. Più team che lavorano in parallelo non saranno in grado di lavorare efficacemente tutti sullo stesso codice (trunk). Se hai solo un piccolo gruppo di persone che lavorano e la tua principale preoccupazione è tagliare un ramo in modo da poter continuare a lavorare mentre torni al ramo per apportare correzioni di bug al codice di produzione corrente che funzionerebbe. Questo è un uso banale delle ramificazioni e non troppo oneroso.

Se hai un sacco di sviluppo parallelo, vorrai avere rami per ciascuno degli sforzi, ma ciò richiederà anche più disciplina: assicurarti che i tuoi rami siano testati e pronti a ricollegarti. La pianificazione delle fusioni in modo che due gruppi non stiano tentando di unirsi contemporaneamente, ecc.

Alcuni rami sono in fase di sviluppo da così tanto tempo che è necessario consentire le fusioni dal tronco al ramo per ridurre il numero di sorprese quando infine si ricollegano al tronco.

Dovrai sperimentare se hai un grande gruppo di sviluppatori e avere un'idea di ciò che funziona nella tua situazione. Ecco una pagina di Microsoft che potrebbe essere in qualche modo utile: http://msdn.microsoft.com/en-us/library/aa730834(VS.80).aspx


4

Stiamo usando il trunk per lo sviluppo principale e il ramo per i lavori di manutenzione delle versioni. Funziona bene. Ma poi i rami dovrebbero essere usati solo per le correzioni di bug, nessuna grande modifica, specialmente sul lato del database, abbiamo una regola che può avvenire solo una modifica dello schema sul trunk principale e mai nel ramo.


1
Perché la regola di nessun database cambia nel ramo?
Bjorn Reppen,

Abbiamo solo la regola perché semplifica l'unione del controllo delle versioni del nostro database. Questo potrebbe essere perché il modo in cui stiamo usando il sequenziamento nei nomi dei file di script per aggiornare il database, sono sicuro che se esiste un metodo diverso, le modifiche al database andrebbero bene per cambiare sul ramo.
adriaanp,

2

Se lavorerai attraverso un ciclo di rilascio, grande caratteristica, verrai abbandonato a un ramo. Altrimenti lavoriamo in trunk e branch per ogni release di produzione nel momento in cui costruiamo.

Le build di produzione precedenti vengono spostate in quel momento in old_production_ e l'attuale versione prod è sempre solo produzione. Tutto ciò che il nostro server di build conosce sulla produzione è come distribuire il ramo di produzione e iniziamo con un trigger di forza.


2

Seguiamo l'approccio trunk = flusso di sviluppo corrente, branch = release (s). Al rilascio al cliente, ramifichiamo il bagagliaio e continuiamo a farlo rotolare in avanti. Dovrai prendere una decisione su quante versioni sei pronto a supportare. Maggiore è il supporto e maggiore sarà l'unione delle correzioni di errori. Cerchiamo di mantenere i nostri clienti su non più di 2 versioni dietro il bagagliaio. (Ad esempio Dev = 1.3, versioni supportate 1.2 e 1.1).


1

Il tronco è generalmente la principale linea di sviluppo.

Le versioni sono diramate e spesso si eseguono lavori sperimentali o importanti sui rami e poi si ricollegano al trunk quando è pronto per essere integrato con la linea di sviluppo principale.


1

Il trunk dovrebbe generalmente essere la principale fonte di sviluppo. Altrimenti passerai molto tempo a fonderti con nuove funzionalità. L'ho visto fare diversamente e di solito porta a molti mal di testa di integrazione dell'ultimo minuto.

Etichettiamo le nostre versioni in modo da poter rispondere rapidamente alle emergenze di produzione senza distribuire lo sviluppo attivo.


1

Per me, dipende dal software che sto usando.

Sotto CVS, lavorerei semplicemente in "trunk" e non taggerei mai / ramo, perché sarebbe stato davvero doloroso fare diversamente.

In SVN, farei la mia roba "bleeding edge" nel trunk, ma quando era il momento di fare un push del server venivo taggato in modo appropriato.

Di recente sono passato a git. Ora trovo che non lavoro mai nel bagagliaio. Invece, utilizzo un ramo sandbox "new-featurename" con nome e quindi unisco in un ramo fisso "produzione corrente". Ora che ci penso, dovrei davvero creare i rami "release-VERSIONNUMBER" prima di ricollegarli alla "produzione attuale" in modo da poter tornare alle versioni stabili precedenti ...


1

Dipende da quanto bene la tua organizzazione / team gestisce le versioni e quale SCM usi.

  • Se ciò che è successivo (nella prossima versione) può essere facilmente pianificato, è meglio svilupparsi nel bagagliaio. La gestione delle filiali richiede più tempo e risorse. Ma se il prossimo non può essere pianificato facilmente (succede sempre nelle organizzazioni più grandi), probabilmente finiresti per impegnarti nella raccolta delle ciliegie (centinaia / migliaia) piuttosto che nei rami (severi o decine).
  • Con Git o Mercurial, la gestione delle filiali è molto più semplice di cv e sovversione. Vorrei optare per la metodologia di trunk / argomenti branch stabile. Questo è ciò che utilizza il team git.git. leggi: http://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html
  • Con Subversion, ho prima applicato la metodologia di sviluppo nel bagagliaio. C'è stato un bel po 'di lavoro quando è arrivata la data di uscita, perché ogni volta che dovevo scegliere cherry commetteva (la mia azienda non è brava a pianificare). Ora sono una specie di esperto di Subversion e conosco abbastanza bene le ramificazioni di manaing in Subversion, quindi mi sto muovendo verso la metodologia stabile di trunk / topic branch. Funziona molto meglio di prima. Ora sto provando il modo in cui funziona il team git.git, anche se probabilmente seguiremo Subversion.

1

Ecco il design SVN che preferisco:

  • radice
    • sviluppo
      • rami
        • feature1
        • feature2
        • ...
      • tronco
    • beta
      • tag
      • tronco
    • pubblicazione
      • tag
      • tronco

Tutto il lavoro viene svolto dallo sviluppo / trunk, ad eccezione delle funzionalità principali che richiedono il proprio ramo. Dopo che il lavoro è stato testato contro sviluppo / trunk, uniamo i problemi testati in beta / trunk. Se necessario, il codice viene testato sul server beta. Quando siamo pronti a implementare alcune modifiche, uniamo le revisioni appropriate in release / trunk e distribuiamo.

I tag possono essere creati nel ramo beta o nel ramo di rilascio in modo da poter tenere traccia di versioni specifiche sia per beta che per versione.

Questo design offre molta flessibilità. Inoltre ci consente di lasciare facilmente le revisioni in beta / trunk e allo stesso tempo di unire gli altri per rilasciare / trunk se alcune revisioni non hanno superato i test in beta.


0

Il metodo che utilizziamo è l'approccio Perforce, che è ampiamente discusso nel grande libro di Laura Wingerd:

http://oreilly.com/catalog/9780596101855/index.html

Mentre il libro è incentrato sulla precisione (Wingerd è un product manager di Perforce), i concetti possono essere applicati a qualsiasi o tutti i VCS.

L'approccio perforce (e la piattaforma) ci ha servito molto bene. È utilizzato in molte aziende (google, Intuit e, ho sentito, Microsoft Windows stesso).

Vale la pena leggere il libro.



0

Non esiste una risposta valida per tutti per la domanda sulla convenzione di sovversione IMHO.

Dipende molto dalla dinamica del progetto e dall'azienda che lo utilizza. In un ambiente molto frenetico, quando un rilascio può avvenire con la stessa frequenza ogni pochi giorni, se si tenta di etichettare e ramificare religiosamente, si finisce con un repository ingestibile. In un tale ambiente, l'approccio derivante da necessità creerebbe un ambiente molto più sostenibile.

Inoltre, nella mia esperienza, è estremamente facile, dal punto di vista amministrativo, passare da una metodologia svn all'altra.

I due approcci che ho conosciuto per funzionare meglio sono il ramo quando necessario e il ramo per attività. Questi sono, ovviamente, una specie di opposto esatto l'uno dell'altro. Come ho detto, è tutto sulla dinamica del progetto.


-1

@Brian R. Bondy: Nota che questa non è una soluzione quando il tuo team raggiunge una certa quantità di ppl / compiti gestiti in parallelo sul progetto.

Una volta che un dipartimento di controllo qualità è coinvolto nel controllo qualità, gli sforzi necessari per fornire un'installazione per ramo in corso sono semplicemente troppo elevati. Pensa a SOA / Clienti / Server / WebServices / Database che devono essere forniti per ramo .

Questa soluzione manca anche della fase di integrazione.


Abbiamo diversi QA coinvolti nel nostro team. Testano ogni funzionalità da un programma di installazione completo creato dal ramo prima che venga unito.
Brian R. Bondy,
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.