2009-02-28 10 views
95

Qual è la migliore strategia di ramificazione da utilizzare quando si desidera eseguire l'integrazione continua?La migliore strategia di ramificazione quando si esegue l'integrazione continua?

  1. uscita Branching: sviluppano sul tronco, mantenere un ramo per ogni release.
  2. Feature Branching: sviluppare ciascuna funzione in un ramo separato, unire solo una volta stabile.

Ha senso utilizzare entrambe queste strategie insieme? In questo modo, si diramano per ogni versione ma si dirama anche per le funzionalità di grandi dimensioni? Una di queste strategie si integra meglio con l'integrazione continua? L'utilizzo dell'integrazione continua avrebbe senso quando si utilizza un trunk instabile?

+2

Nota a margine: alcuni sostengono che anche se vengono introdotte nuove funzionalità, tutto dovrebbe sempre essere stabile. D'altra parte, potrebbe essere in qualche modo idealistico. –

+0

Controlla anche questo articolo: http://www.yegor256.com/2014/07/21/read-only-master-branch.html – yegor256

risposta

9

Personalmente trovo molto più pulito avere un tronco stabile e funzionalità di ramificazione. In questo modo, i tester e simili possono rimanere su una singola "versione" e aggiornare dal trunk per testare qualsiasi funzionalità che sia completa di codice.

Anche se più sviluppatori stanno lavorando su funzionalità diverse, possono tutti avere le proprie diramazioni separate, quindi unire al trunk quando hanno finito e inviare una funzionalità da testare senza che il tester debba passare a più filiali per testare caratteristiche diverse.

Come bonus aggiuntivo, c'è un certo livello di test di integrazione che viene automaticamente.

+0

sì, ma come funziona con l'integrazione continua? – eglasius

+0

Inoltre, si continua a ramificarsi e taggare per ogni versione principale? O semplicemente taggare? – KingNestor

+1

Funziona bene con CI finché i rami funzione vengono uniti nel bagagliaio con una certa disciplina in modo da non avere build rotte. Faccio branch e tag per ogni release di produzione che verrà utilizzata solo per il bug fixing. Questo può essere unito immediatamente al tronco stabile. – Adnan

0

Il modo in cui lo vedo si desidera avere un insieme limitato di rami in cui è possibile mettere a fuoco. Dal momento che desideri test, metriche sulla qualità del codice e molte cose interessanti da eseguire con le build, avere troppi report probabilmente ti farà perdere le informazioni.

Quando e cosa ramificare, in genere dipende dalle dimensioni del team e dalle dimensioni delle funzionalità sviluppate. Non penso che ci sia una regola d'oro. Assicurati di utilizzare una strategia in cui puoi ricevere feedback in anticipo/spesso e ciò include il coinvolgimento della qualità sin dall'inizio delle funzionalità. Il bit di qualità, significa che mentre si sta automatizzando mentre il team si sviluppa, se si dirige verso un set di funzionalità di grandi dimensioni che un team sta creando, è necessario coinvolgere anche la qualità nel team.

ps Dove hai ottenuto questi riferimenti di approccio? - non ritiene che quei grafici rappresentino tutte le opzioni

Aggiornamento 1: Espansione sul motivo per cui ho detto che non è una regola d'oro. Fondamentalmente per team relativamente piccoli, ho trovato la cosa migliore usando un approccio che è un mix. I rami feature vengono creati se è qualcosa di lungo e parte del team continuerà ad aggiungere funzionalità più piccole.

+0

http: //blogs.open.collab. net/svn/2007/11/branching-strat.html – KingNestor

+0

Ne ha anche altri. Ma mi sento come Feature Branching e Release Branching sono i 2 più comuni. – KingNestor

21

La risposta dipende dalle dimensioni del team e dalla qualità del controllo del codice sorgente e dalla capacità di unire correttamente set di modifiche complessi. Ad esempio nel controllo del codice sorgente completo come CVS o SVN la fusione può essere difficile e potresti stare meglio con il primo modello, mentre se utilizzi un sistema più complesso come IBM ClearCase e con un team di dimensioni maggiori potresti essere migliore con il secondo modello o una combinazione dei due.

Personalmente, separerei il modello di ramo di funzionalità, in cui ogni caratteristica principale è sviluppata su un ramo separato, con sotto-rami di attività per ogni modifica eseguita da uno sviluppatore individuale. Man mano che le funzioni si stabilizzano, vengono unite al tronco, che si mantiene ragionevolmente stabile e superando tutti i test di regressione in ogni momento.Quando ti avvicini alla fine del ciclo di rilascio e tutte le ramificazioni delle feature si uniscono, ti stabilizzi e si ramifichi un ramo del sistema di rilascio su cui fai solo correzioni di bug di stabilità e backport necessari, mentre il tronco viene utilizzato per lo sviluppo della prossima release e tu di nuovo diramazione per nuove filiali di funzionalità. E così via.

In questo modo il trunk contiene sempre il codice più recente, ma si riesce a mantenerlo ragionevolmente stabile, creando etichette stabili (tag) sulle principali modifiche e fusioni di funzionalità, i rami di funzionalità sono sviluppo veloce con integrazione continua e attività individuali le filiali possono essere spesso aggiornate dal ramo della funzione per consentire a tutti di lavorare sulla stessa funzione in sincronia, senza tuttavia influire sugli altri team che lavorano su funzionalità diverse.

Allo stesso tempo si ha attraverso la cronologia una serie di rami di rilascio, in cui è possibile fornire backport, supporto e correzioni di errori per i propri clienti che per qualsiasi motivo rimangono su versioni precedenti del prodotto o anche solo l'ultima versione rilasciata. Come nel caso del trunk, non si imposta l'integrazione continua sui rami di rilascio, ma vengono attentamente integrati al superamento di tutti i test di regressione e di altri controlli di qualità.

Se per qualche motivo due funzioni sono co-dipendenti e devono essere apportate modifiche reciproche, è possibile considerare di sviluppare entrambi sullo stesso ramo di funzionalità o di richiedere che le funzioni uniscano regolarmente parti stabili del codice a trunk e quindi aggiorna le modifiche dal tronco per scambiare il codice tra i rami del tronco. Oppure, se è necessario isolare queste due funzioni da altre, è possibile creare un ramo comune da cui si diramano i rami delle funzioni e che è possibile utilizzare per scambiare il codice tra le funzioni.

Il modello di cui sopra non molto senso con squadre sotto 50 sviluppatori e sistema di controllo del codice sorgente senza rami radi e la corretta funzionalità di fusione come CVS o SVN, che sarebbe solo rendere questo prodotto a un incubo da configurare, gestire e integrare.

+5

Non sono sicuro di essere d'accordo sul fatto che ciò che descrivi non ha senso per i team con meno di 50 sviluppatori. Vedo anche benefici per squadre molto più piccole. +1 – Aardvark

+2

Ovviamente, ci sono benefici per squadre di qualsiasi dimensione. La domanda è in quale misura della squadra i benefici superano i costi associati a un processo pesante. –

20

Trovo che l'argomento sia davvero interessante poiché faccio molto affidamento sui rami del mio lavoro quotidiano.

  • Ricordo Mark Shuttleworth che proponeva un modello su come mantenere il ramo principale incontaminato andando al di là dell'IC convenzionale. L'ho postato su di esso here.
  • Dato che ho familiarità con Cruise Control, ho anche eseguito il blogger su rami attività e CI here. È un tutorial passo dopo passo che spiega come farlo con Plastic SCM.
  • Infine, ho trovato alcuni degli argomenti su CI (e potenzialmente parlando di diramazione) nel libro di Duvall su CI very interesting too.

Spero che i link siano interessanti.

+0

Abbiamo aggiunto il supporto a Bamboo per fare il ramo per attività http://codicesoftware.blogspot.com/2012/02/setting-up-bamboo-server-to-test-task.html, e sembra che la loro versione più recente lo farà in modo nativo con diversi controlli di versione, tra cui dvcs. – pablo

2

Fintanto che comprendi i principi, puoi sempre reinventare le migliori pratiche. Se non comprendi i principi, le migliori pratiche ti porteranno così lontano prima di andare in pezzi a causa di alcuni requisiti esterni in conflitto.

Per la migliore introduzione nel Modello Mainline, leggere questo: https://web.archive.org/web/20120304070315/http://oreilly.com/catalog/practicalperforce/chapter/ch07.pdf

Leggi il link. Una volta che hai le basi, leggi il seguente articolo del venerabile Henrik Kniberg. Ti aiuterà a relazionare il modello principale con l'integrazione continua.

http://www.infoq.com/articles/agile-version-control

+0

Capitolo O'Reilly non più accessibile –

+1

@JasonS - aggiornato a un collegamento archive.org – zvolkov

5

Stampa rami sono molto utili, e addirittura assolutamente necessaria, se è necessario mantenere diverse versioni della tua app.

I rami di funzionalità sono anche molto convenienti, in particolare se uno sviluppatore deve lavorare su un enorme cambiamento, mentre altri ancora rilasciano nuove versioni.

Quindi per me usare entrambi i meccanismi è un'ottima strategia.

Collegamento interessante da Book of SVN.

2

L'integrazione continua non dovrebbe essere un fattore determinante nella determinazione della strategia di diramazione. Il tuo approccio alla ramificazione dovrebbe essere selezionato in base al tuo team, al sistema in fase di sviluppo e agli strumenti disponibili.

Detto questo ...

  • non c'è alcun motivo per cui CI non potrebbe essere utilizzato in entrambi gli approcci che descrivi
  • quegli approcci funzionano abbastanza bene in combinazione
  • nessuno dei due lavoro "migliore" rispetto agli altri
  • CI senso totale, con un tronco instabile

Tutto questo era answere d nella quarta domanda sulla pagina che hai preso i diagrammi da: http://blogs.collab.net/subversion/2007/11/branching-strat/

4

Mi sono recentemente avvicinato allo this model quando uso git. Sebbene la tua domanda sia contrassegnata come "svn", potresti comunque riuscire a farne un uso.

L'integrazione continua può in qualche misura avvenire nel ramo "sviluppo" (o in qualsiasi modo venga chiamato) in questo modello, sebbene disporre di rami di funzionalità di lunga durata per le versioni future non lo renderebbe così rigido da considerare ogni cambiamento che si verifica da codice da qualche parte. La domanda rimane, che tu lo voglia davvero.

1

Quando abbiamo avviato il nostro team, abbiamo ereditato una strategia basata sul rilascio dal fornitore che originariamente ha sviluppato il sistema di cui eravamo in procinto di diventare responsabili. Ha funzionato fino al momento in cui i nostri clienti hanno richiesto che non fossero incluse in una versione diverse funzionalità sviluppate (ad esempio ~ 250k linee di codice, ~ 2500 file, Scrum con XP SDLC).

Quindi abbiamo iniziato a esaminare i rami basati sulle funzionalità. Ciò ha funzionato anche per un po '- come per 2 mesi fino al punto in cui ci siamo resi conto che il nostro processo di test di regressione avrebbe richiesto più di 2 settimane, il che combinato con l'incertezza di ciò che sarebbe stato rilasciato creava un enorme disagio.

L'ultimo "chiodo nella bara" delle strategie SC puro è arrivato quando abbiamo deciso che dovevamo avere 1. tronco stabile e 2. La produzione dovrebbe contenere BINARI testati ST, UAT e Regressione (non solo fonte - pensa CC.)

Questo ci ha portato a ideare una strategia che sia un ibrido tra funzionalità e strategie SC basate su release.

Quindi abbiamo un baule. Ogni sprint si dirama verso il ramo di sprint (per le persone non agili - uno sprint è solo uno sforzo di sviluppo in time-box con output variabile basato sulla complessità.) Dal ramo di sprint creiamo i rami di feature e lo sviluppo parallelo inizia in essi. Una volta che le funzionalità sono state completate e testate dal sistema, e riceviamo l'intento di distribuirle, queste vengono unite al ramo sprint: alcune possono fluttuare tra diversi sprint, di solito quelli più complessi. Una volta che lo sprint è vicino alla fine e le funzionalità sono complete ..."rinominiamo" il ramo sprint in "regressione" (questo consente a CruiseControl di riprenderlo senza alcuna riconfigurazione) e quindi il test di regressione/integrazione inizia sull'EAR cc-costruito. Quando tutto è fatto, va in produzione.

In breve, per lo sviluppo, il test di sistema e la funzionalità UAT vengono utilizzate le diramazioni basate sulle funzionalità. Il ramo sprint (in realtà il ramo di rilascio) viene utilizzato per unire selettivamente funzionalità on-demand e test di integrazione.

Ora questa è una domanda per la comunità: ovviamente abbiamo problemi a eseguire l'integrazione continua a causa del fatto che lo sviluppo si verifica su molti rami e il sovraccarico di riconfigurazione di CruiseControl. Qualcuno può suggerire e consigliare?

+0

Non sono necessariamente d'accordo con le conclusioni, ma grazie per la discussione del vostro processo. Non esiste una soluzione valida per tutti. Il collegamento – RaoulRubin

5

Penso che entrambe le strategie possano essere utilizzate con lo sviluppo continuo a patto di ricordare uno dei principi chiave che ogni sviluppatore si impegna a gestire ogni giorno.

http://martinfowler.com/articles/continuousIntegration.html#EveryoneCommitsToTheMainlineEveryDay

EDIT

Ho fatto qualche lettura di this book sulla CI e gli autori suggeriscono che faccio ramificazione dal rilascio è la loro strategia di ramificazione preferito. Devo essere d'accordo. La ramificazione per feature non ha senso per me quando si usa CI.

Proverò a spiegare perché sto pensando in questo modo. Supponiamo che tre sviluppatori prendano una filiale per lavorare su una funzione. Ogni funzionalità richiederà diversi giorni o settimane per terminare. Per garantire che la squadra si integri continuamente, devono impegnarsi nella filiale principale almeno una volta al giorno. Non appena iniziano a farlo, perdono il vantaggio di creare un branch di funzionalità. Le loro modifiche non sono più separate da tutte le altre modifiche dello sviluppatore. Stando così le cose, perché preoccuparsi di creare rami di funzionalità in primo luogo?

L'utilizzo della ramificazione per rilascio richiede una fusione molto minore tra i rami (sempre una buona cosa), assicura che tutte le modifiche vengano integrate al più presto e (se eseguite correttamente) assicurino che il codice sia sempre pronto per il rilascio. Il lato negativo della ramificazione per versione è che devi essere molto più attento ai cambiamenti. Per esempio. Il refactoring di grandi dimensioni deve essere eseguito in modo incrementale e se hai già integrato una nuova funzione che non desideri nella prossima versione, deve essere nascosta utilizzando una sorta di meccanismo feature toggling.

ALTRO EDIT

C'è più di un parere su questo tema. Ecco un post sul blog che è pro caratteristica ramificazione con CI

http://jamesmckay.net/2011/07/why-does-martin-fowler-not-understand-feature-branches/

+0

non funziona – Sam

+0

interessante, non riesco più a trovare questo post. –

-3

Credo che gli strumenti utilizzati sono un grande fattore qui.

  • Se si utilizza Subversion, attenersi all'opzione 1 e rilasciare dalle filiali.
  • Se si utilizza GIT, l'opzione 2 funzionerà correttamente.
+2

La ramificazione delle feature può essere facilmente raggiunta con qualsiasi SCM – hdost