Come si mantengono il codice di sviluppo e il codice di produzione? [chiuso]


136

Quali sono le migliori pratiche e le regole empiriche da seguire mantenendo il codice? È buona norma avere solo il codice pronto per la produzione nel ramo di sviluppo o dovrebbe essere disponibile l'ultimo codice non testato nel ramo di sviluppo?

Come mantenete il vostro codice di sviluppo e il codice di produzione?

Modifica - Domanda supplementare - Il tuo team di sviluppo segue il protocollo "commit-as-as-as-just-as-as-how-as-how-as-only-if-the-code-contiene-minor-bugs-or-is-incomplete" or "commit- Protocollo ONLY-perfect-code "durante il commit del codice nella filiale DEVELOPMENT?


Ho già risposto a una domanda simile (o bene, una domanda nello stesso spazio / direzione), quindi potresti voler dare un'occhiata a questa domanda: quali sono alcune buone strategie per consentire l'aggiornamento rapido delle applicazioni distribuite?
Fino al

@revo: aspetta ... la mia risposta del 2008 non è aggiornata? :) Suppongo che sia davvero. Sono passati più di 10 anni: ho modificato la mia risposta.
VonC

Risposte:


114

Aggiornamento 2019:

In questi giorni, la domanda verrebbe vista in un contesto usando Git e 10 anni di utilizzo di quel flusso di lavoro di sviluppo distribuito (collaborando principalmente tramite GitHub ) mostrano le migliori pratiche generali:

  • masterè il ramo pronto per essere distribuito in produzione in qualsiasi momento: la versione successiva, con un insieme selezionato di rami di caratteristiche uniti master.
  • dev(o ramo di integrazione, o ' next') è quello in cui vengono testati insieme il ramo di funzionalità selezionato per la versione successiva
  • maintenance(o hot-fix) branch è quello per l'evoluzione della versione corrente / correzioni di bug, con possibili fusioni indietro a deve omaster

Questo tipo di flusso di lavoro (in cui non si unisce deva master, ma dove si uniscono unico ramo funzione per dev, poi, se selezionato, per master, al fine di essere in grado di cadere facilmente caratterizzare rami non è pronto per la prossima release) è implementato nel Git repo stesso, con gitworkflow (una parola, illustrata qui ).
Vedi di più su rocketraman/gitworkflow. La storia di questo sviluppo vs Trunk-Based-Development è annotata nei commenti e nelle discussioni di questo articolo di Adam Dymitruk .

https://github.com/rocketraman/gitworkflow/raw/master/docs/images/topicgraduation.png

(fonte: Gitworkflow: A Primer orientato alle attività )

Nota: in quel flusso di lavoro distribuito, è possibile eseguire il commit ogni volta che si desidera e inviare senza problemi a un ramo personale un WIP (Work In Progress): sarà possibile riorganizzare (git rebase) i propri commit prima di farli parte di un ramo di funzionalità.


Risposta originale (ottobre 2008, 10+ anni fa)

Tutto dipende dalla natura sequenziale della gestione delle versioni

Innanzitutto, tutto nel tuo baule è davvero per la prossima versione ? Potresti scoprire che alcune delle funzioni attualmente sviluppate sono:

  • troppo complicato e deve ancora essere raffinato
  • non pronto in tempo
  • interessante ma non per questa prossima versione

In questo caso, trunk dovrebbe contenere qualsiasi sforzo di sviluppo corrente, ma un ramo di rilascio definito prima della prossima versione può fungere da ramo di consolidamento in cui solo il codice appropriato (convalidato per la versione successiva) viene unito, quindi corretto durante la fase di omologazione, e infine congelato mentre entra in produzione.

Quando si tratta di codice di produzione, è necessario anche gestire i rami delle patch , tenendo presente che:

  • il primo set di patch potrebbe effettivamente iniziare prima del primo rilascio in produzione (il che significa che sai che entrerai in produzione con alcuni bug che non puoi correggere in tempo, ma puoi iniziare a lavorare per quei bug in un ramo separato)
  • le altre filiali di patch avranno il lusso di partire da un'etichetta di produzione ben definita

Quando si tratta di dev branch, puoi avere un trunk, a meno che tu non abbia altri sforzi di sviluppo che devi compiere in parallelo come:

  • refactoring massiccio
  • test di una nuova libreria tecnica che potrebbe cambiare il modo in cui chiamate le cose in altre classi
  • inizio di un nuovo ciclo di rilascio in cui è necessario incorporare importanti modifiche architettoniche.

Ora, se il tuo ciclo di rilascio dello sviluppo è molto sequenziale, puoi semplicemente andare come suggeriscono le altre risposte: un trunk e diversi rami di rilascio. Funziona con progetti di piccole dimensioni in cui tutto lo sviluppo entrerà sicuramente nella prossima versione e può essere semplicemente congelato e fungere da punto di partenza per il ramo di rilascio, dove possono essere applicate le patch. Questo è il processo nominale, ma non appena avrai un progetto più complesso ... non sarà più sufficiente.


Per rispondere al commento di Ville M.:

  • tieni presente che il ramo di sviluppo non significa "un ramo per sviluppatore" (che innescherebbe "unire follia", in quanto ogni sviluppatore dovrebbe unire il lavoro di un altro per vedere / ottenere il proprio lavoro), ma un ramo di sviluppo per sviluppo sforzo.
  • Quando tali sforzi devono essere ricondotti nel trunk (o in qualsiasi altro ramo "principale" o di rilascio definito), questo è il lavoro dello sviluppatore, non - ripeto, NON - il Manager SC (che non saprebbe come risolvere qualsiasi unione in conflitto). Il responsabile del progetto può supervisionare l'unione, ovvero assicurarsi che inizi / termini in tempo.
  • chiunque tu scelga per fare effettivamente l'unione, il più importante è:
    • disporre di unit test e / o ambienti di assemblaggio in cui è possibile distribuire / testare il risultato dell'unione.
    • avere definito un tag prima dell'inizio della fusione per poter tornare allo stato precedente se detta fusione si rivela troppo complessa o piuttosto lunga da risolvere.

1
@Adam Grazie per la modifica e scusate per non aver impostato prima l'attribuzione corretta.
VonC

Ha! Nessun problema. Hai fatto così tanto per la comunità qui, difficilmente puoi incolpare nulla. Sono solo felice che abbiamo persone come te che fanno così tanto lavoro a beneficio di tutti in tutto il mondo!
Adam Dymitruk,

43

Noi usiamo:

  • ramo di sviluppo esclusivamente

fino al completamento del progetto o non stiamo creando una versione cardine (ad es. demo del prodotto, versione di presentazione), quindi (regolarmente) ramifichiamo il nostro ramo di sviluppo corrente in:

  • ramo di rilascio

Nessuna nuova funzionalità va nel ramo di rilascio. Solo i bug importanti vengono corretti nel ramo di rilascio e il codice per correggere questi bug viene reintegrato nel ramo di sviluppo.

Il processo in due parti con uno sviluppo e un ramo stabile (rilascio) ci semplifica la vita e non credo che potremmo migliorarne qualsiasi parte introducendo più rami. Ogni ramo ha anche il proprio processo di compilazione, il che significa che ogni paio di minuti viene generato un nuovo processo di compilazione e quindi dopo un check-in del codice abbiamo un nuovo eseguibile di tutte le versioni di build e rami entro circa mezz'ora.

Occasionalmente abbiamo anche filiali per un singolo sviluppatore che lavora su una tecnologia nuova e non provata o che crea una prova di concetto. Ma generalmente viene fatto solo se le modifiche riguardano molte parti della base di codice. Ciò accade in media ogni 3-4 mesi e tale ramo viene solitamente reintegrato (o demolito) entro un mese o due.

Generalmente non mi piace l'idea di ogni sviluppatore che lavora nel suo stesso ramo, perché "salti vai e vai direttamente all'inferno dell'integrazione". Lo sconsiglio vivamente. Se hai una base di codice comune, dovresti lavorarci tutti insieme. Questo rende gli sviluppatori più cauti riguardo ai loro check-in e, con l'esperienza, ogni programmatore sa quali modifiche stanno potenzialmente rompendo la build e quindi i test sono più rigorosi in questi casi.

Alla domanda iniziale per il check-in:

Se è necessario solo il CODICE PERFETTO da archiviare, in realtà nulla deve essere archiviato. Nessun codice è perfetto e per il QA per verificarlo e testarlo, è necessario che si trovi nel ramo di sviluppo in modo da poter creare un nuovo eseguibile.

Per noi ciò significa che una volta che una funzionalità è completa e testata dallo sviluppatore, viene archiviata. Può anche essere verificata se ci sono bug noti (non fatali), ma in quel caso le persone che sarebbero interessate dal bug sono di solito informato. È anche possibile eseguire il check-in del codice incompleto e in fase di elaborazione, ma solo se non causa effetti negativi evidenti, come arresti anomali o interruzione della funzionalità esistente.

Ogni tanto un inevitabile check-in combinato di codice e dati renderà il programma inutilizzabile fino alla creazione del nuovo codice. Il minimo che facciamo è aggiungere un "ATTESA PER LA COSTRUZIONE" nel commento del check-in e / o inviare una e-mail.


1
L'ho votato. Questo è simile a quello che facciamo, ma stiamo apportando tutte le modifiche allo sviluppo e quindi provando a unire quelle correzioni di bug nel ramo di rilascio. Non funziona. Tuttavia, penso che se cambiamo per fare tutte le correzioni di bug in versione e ci uniamo allo sviluppo, questo lo risolverà.
TheCodeMonk il

2
Implichi che il QA test il ramo di sviluppo, non sarebbe meglio se controllassero il ramo di rilascio? In questo modo potrei iniziare a lavorare sulla mia nuova funzionalità pazza che non sarà inclusa nella prossima versione (e potrebbe interrompere qualcosa) mentre in quel momento il QA testerà il codice esistente senza che la mia nuova funzionalità si interfacci?
BornToCode

15

Per quello che vale, ecco come lo facciamo.

La maggior parte dello sviluppo viene eseguito in trunk, anche se le caratteristiche sperimentali o le cose che potrebbero rompere il sistema tendono in modo significativo a ottenere il proprio ramo. Questo funziona abbastanza bene in quanto significa che ogni sviluppatore ha sempre l'ultima versione di tutto nella sua copia di lavoro.

Significa che è importante mantenere il tronco in ordine vagamente funzionante, poiché è perfettamente possibile romperlo completamente. In pratica ciò non accade spesso ed è raramente un problema significativo.

Per una versione di produzione, eseguiamo il branch branch, smettiamo di aggiungere nuove funzionalità e lavoriamo sulla correzione di bug e testiamo il branch (fondendoli regolarmente in trunk) fino a quando non è pronto per il rilascio. A quel punto facciamo un'ultima fusione nel trunk per assicurarci che tutto sia lì dentro, quindi rilasciamo.

La manutenzione può quindi essere eseguita sul ramo di rilascio, se necessario, e tali correzioni possono essere facilmente ricondotte nel trunk.

Non pretendo che questo sia un sistema perfetto (e ha ancora alcuni buchi - non credo che la nostra gestione delle versioni sia ancora un processo abbastanza stretto), ma funziona abbastanza bene.


funziona abbastanza bene ed è abbastanza semplice anche per gli sviluppatori di soli codici non-vcs-druids.
Matthieu,

12

Perché nessuno lo menziona ancora? Un modello di ramificazione Git di successo .

È per me il modello di ramificazione definitivo!

Se il tuo progetto è piccolo, non usare sempre tutti i diversi rami (forse potresti saltare i rami delle caratteristiche per piccole funzioni). Ma per il resto, è il modo di farlo!

modello ramificato


4
Sì, tranne se spesso è un po 'troppo complesso / completo, come illustra scottchacon.com/2011/08/31/github-flow.html .
VonC,

Sono d'accordo. Comprendi il modello di ramificazione del flusso git (che risolve molti problemi) e semplificalo per soddisfare le tue esigenze. E il flusso di GitHub richiede una distribuzione rapida ma non è sempre possibile ... È più o meno il modello di ramificazione che usiamo nel mio progetto (per semplificare le cose) ma abbiamo affrontato un caso in cui avremmo adorato usare il modello git-flow: (e questo ci ha messo in una merda davvero grande :(
Philippe

1
Per come la vedo io, questo praticamente copia tutto ciò che VonC ha detto all'incirca 1 anno prima (sulla sua risposta), ma in modo più dettagliato e con belle foto!
Cregox,

6

Codice di sviluppo sui rami, codice Live taggato su Trunk.

Non è necessario che vi sia una regola "impegna solo codice perfetto": tutto ciò che manca allo sviluppatore dovrebbe essere raccolto in quattro punti: revisione del codice, test delle filiali, test di regressione, test di QA finale.

Ecco una spiegazione dettagliata più dettagliata:

  1. Fai tutto lo sviluppo su una filiale, impegnandoti regolarmente mentre vai.
  2. Revisione indipendente del codice delle modifiche una volta completato tutto lo sviluppo.
  3. Quindi passare il ramo su Test.
  4. Una volta completato il test del ramo, unisci il codice nel ramo Rilascia candidato.
  5. Il ramo Release Candidate viene testato per la regressione dopo ogni singola unione.
  6. Test QA e UA finali eseguiti su RC dopo la fusione di tutti i rami di sviluppo.
  7. Una volta passati QA e UAT, unire il ramo di rilascio nel ramo MAIN / TRUNK.
  8. Infine, tagga il Trunk a quel punto e distribuisci quel tag su Live.


3

Risolviamo questo problema separando completamente il codice di produzione (il trunk principale) dal codice di sviluppo (dove ogni sviluppatore ha il suo ramo).

Nessun codice è consentito nel codice di produzione prima che sia stato accuratamente controllato (da QA e revisori del codice).

In questo modo non c'è confusione su quale codice funzioni, è sempre il ramo principale.


2

Oh sì - un'altra cosa - manteniamo il codice di non produzione (ovvero quello che NON verrà MAI rilasciato - ad esempio script di strumenti, utilità di test) in cvs HEAD. Di solito deve essere chiaramente indicato in modo che nessuno "accidentalmente" lo rilasci.


2
forse questo sarebbe meglio come una modifica alla risposta precedente.
Richard Harrison,

6
Ha detto CVS. :-)
Fino al

2

Sviluppiamo su tronco che viene poi ramificato ogni due settimane e messo in produzione. Nel ramo vengono risolti solo i bug critici, il resto può attendere altre due settimane.

Per trunk l'unica regola è che un commit non dovrebbe interrompere nulla. Per gestire il codice di cancellazione e il codice non testato, aggiungiamo semplicemente le istruzioni appropriate per semplificare l'attivazione e la disattivazione.

Fondamentalmente sarebbe possibile ramificare il tronco in qualsiasi momento e metterlo in produzione.


0

Uso git e ho 2 rami: master e maint

  • master - codice di sviluppo
  • manutenzione - codice di produzione

quando rilascio il codice in produzione, lo taggo e unisco il master al ramo di manutenzione . Distribuisco sempre dal ramo di manutenzione . Patch dal ramo di sviluppo Le seleziono per ramificare e distribuire le patch.


0

Abbiamo un ramo "release" che contiene ciò che è attualmente in produzione o verrà distribuito a breve (già superato la maggior parte del QA)

Ogni progetto, o in alcuni casi un'altra unità, ha un proprio ramo che è ramificato dal rilascio.

Le modifiche vengono impegnate, dagli sviluppatori del progetto, nel proprio ramo del progetto. Periodicamente, la versione viene nuovamente riunita in un ramo di sviluppo.

Una volta che i pacchetti di lavoro sul ramo sono tutti QA (unit test, test di sistema, revisione del codice, revisione del QA ecc.), Il ramo viene unito al ramo di rilascio. Le nuove build vengono create dal ramo di rilascio e la convalida finale viene eseguita su quella versione.

Il processo è sostanzialmente OK fino a quando non viene rilevato un problema dopo che è stata eseguita un'unione. Se un WP viene "bloccato" dopo essere stato unito, regge tutto dopo di esso fino a quando non viene risolto (non possiamo fare un'altra versione fino a quando non viene rilasciato quello bloccato).


È anche un po 'flessibile - un cambiamento molto banale potrebbe accadere direttamente sul ramo di rilascio se fosse rilasciato su una scala di tempo molto breve (come 1-2 giorni o giù di lì).

Se per qualche motivo fosse stata apportata una modifica direttamente alla produzione (un problema di produzione critico per il cliente che richiedeva una correzione immediata del codice da correggere), tali modifiche verrebbero ripristinate in BRANCH_RELEASE. Non succede quasi mai.


0

Dipende dal progetto. Il nostro codice web è registrato in modo abbastanza coerente, mentre il nostro codice applicazione è verificato solo se compilato. Ho notato che questo è abbastanza simile a come rilasciamo le cose. I contenuti Web aumentano ogni volta che possono, mentre le applicazioni raggiungono una scadenza rigida. Tuttavia, non ho visto una perdita di qualità in nessuno dei due metodi.

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.