Strategia di ramificazione Git per codice inedito di lunga durata


15

Nel nostro team, oltre alle singole unità di lavoro (Storie), abbiamo temi di lavoro più lunghi (Epiche). Storie multiple fanno un'epopea.

Tradizionalmente abbiamo avuto rami di funzionalità per ogni storia e li abbiamo uniti direttamente al padrone quando superano il QA. Tuttavia, vorremmo iniziare a trattenere il rilascio delle storie completate in un'epica fino a quando l'epica non sarà considerata "completa". Rilasceremo queste funzionalità in produzione solo quando l'intera Epic sarà chiusa. Inoltre, abbiamo un server di build notturno: vorremmo che tutte le Storie chiuse (incluse quelle che fanno parte di Epic incomplete) fossero distribuite automaticamente su questo server notturno.

Ci sono suggerimenti su come gestire il nostro repository per raggiungere questo obiettivo? Ho preso in considerazione l'introduzione di "rami epici", in cui avremmo unito storie chiuse al ramo epico correlato anziché dirette al maestro, ma le mie preoccupazioni sono:

  • Mi preoccupo dei conflitti di unione che possono sorgere se i rami epici vengono tenuti aperti a lungo
  • Le build notturne richiederebbero la fusione di tutti i rami epici in un ramo "build notturno". Ancora una volta, potrebbero sorgere conflitti di unione, e questo deve essere fatto automaticamente

Risposte:


23

Suggerimento semplice: non farlo.

i rami git non sono per le forchette a lungo termine del codice, come discusso qui e https://blog.newrelic.com/2012/11/14/long-running-branches-considered-harmful/ . Le filiali sono meglio trattate come cose transitorie utilizzate per organizzare i commit da un singolo sviluppatore a livello quotidiano. Quindi, se hanno un nome che corrisponde a qualcosa che un project manager (figuriamoci l'utente finale) potrebbe interessare a te, stai facendo qualcosa di sbagliato.

La pratica raccomandata è quella di utilizzare l'integrazione continua con gli interruttori funzione o diramazione per astrazione per garantire che:

  • tutto il codice è integrato in ogni momento (almeno ogni giorno, preferibilmente più spesso)
  • ciò che viene distribuito è sotto controllo esplicito.

1
Sospettavo che questa potesse essere una risposta popolare! Le mie principali preoccupazioni sono l'overhead di mantenere sempre sia l'implementazione 'live' che 'next', e richiede anche che lo sviluppatore che lavora su una funzionalità conosca in anticipo per creare cambiamenti come nuove funzionalità parallele invece di aggiornare (/ sostituire) il funzionalità esistente. Immagino che richieda un cambiamento di mentalità più ampio nella squadra.
Sitati,

Va bene usare i rami per sviluppare il codice, ma non usarli mai per archiviare il codice. Quindi, se non si è sicuri se un'attività è una correzione di 30 minuti o una rilavorazione di 2 settimane, quindi iniziare su un ramo. Non appena sai, unisci o rifratta in un'astrazione / alternanza, quindi unisci.
soru,

@Sitati: ho appena unito un po 'di codice che è stato nel ramo di una funzione negli ultimi quattro mesi. Nel frattempo develsiamo passati a CMake da Autotools, abbiamo introdotto Travis CI, riformattato il codice. Alla fine è stato più semplice comprendere la nuova funzionalità e applicarla manualmente develpiuttosto che tentare di unirla. Abbiamo anche chiesto ai nuovi studenti Master di sviluppare una nuova funzione in un ramo che si sono ramificati quando hanno iniziato la tesi. Dopo un anno l'hanno spinto e non c'è stato nessuno sforzo per farlo fondere di nuovo, quindi è diventato più difficile fondersi giorno dopo giorno.
Martin Ueding,

2
Il post sul blog collegato ora ha 5 anni. Odio le funzionalità. Cosa c'è che non va nella diramazione a lungo termine, che si fonde regolarmente nel ramo delle funzionalità dalla rete principale e aggiunge l'integrazione continua al ramo delle funzioni a lungo termine?
Jason Kelley il

CI è il nome di un processo, non uno strumento. Se si dispone di più di un ramo di funzionalità, normalmente non si integreranno continuamente tra loro. Ciò significa trovare i problemi più tardi piuttosto che prima.
soru,

1

Penso che questo sia un problema piuttosto comune e si riduce a scegliere quali funzionalità includere in una versione dopo che le funzionalità sono state codificate piuttosto che prima.

per esempio.

Ho le caratteristiche A, B e C per v2 del mio prodotto. B e C sono correlati, non voglio rilasciare B a meno che anche C non sia finito.

Ho tre sviluppatori che lavorano tutti insieme sulle funzionalità.

Ho una data di uscita in pietra D

B è finito e unito, A è finito e unito. C è ritardato ... cosa devo fare ?!

Non credo che ci sia una soluzione tecnica a questo problema. Si desidera rilasciare una versione non testata del prodotto con solo la funzione A inclusa. A meno che non si uniscano e testino tutte le possibili combinazioni di funzionalità, questa sarà sempre una possibilità.

La soluzione è più umana. Hai perso la data di uscita e devi respingerla.


1

Questo è un problema difficile ma che molte persone devono affrontare. Preferisco usare la configurazione di Gitflow come punto di partenza.

Sviluppo -> Nuove cose in lavorazione su
Master -> Oggetti finiti che necessitano di test di produzione -> Oggetti che sono stati pubblicati sulla produzione.

A funzioni minori (più brevi) creo un ramo dallo sviluppo, faccio il lavoro lì e unisco il ramo allo sviluppo.

Per le funzionalità principali (a lungo termine) creo un ramo dallo sviluppo, creo rami più piccoli da quel ramo, quindi ricollego al primo ramo. Una volta completata la funzionalità principale, torna al ramo di sviluppo.

A intervalli regolari (dipende dal progetto), lo sviluppo viene nuovamente unito al master e inizia un ciclo di test. Se nel test vengono rilevate delle correzioni, queste vengono eseguite nel ramo principale (ramo secondario quindi unisci). E lo sviluppo può continuare sul ramo principale durante i test.

In qualsiasi momento il master dovrebbe essere unito allo sviluppo e lo sviluppo dovrebbe essere unito a uno qualsiasi dei suoi rami secondari a lungo termine.

il maestro dovrebbe sempre (in teoria) essere pronto per la produzione. Lo sviluppo dovrebbe sempre (in teoria) essere pronto per la produzione. L'unica ragione per cui c'è una differenza nel fornire un solido set di funzionalità che i tester possono testare.

Quando è pronto, un commit nel master testato viene unito alla produzione e la distribuzione in produzione avviene da quel ramo. Gli HOTFIX che devono essere eseguiti in caso di emergenza possono quindi avvenire nel ramo di produzione senza dover unirsi al master (che può avere molte modifiche non testate).

Il mio albero normale sembra

 LongTerm -> Development -> Master -> Production    
 LongTerm <- Development      |            |  
     |       Development -> Master         |  
 LongTerm <- Development -> Master         |  
             Development <- Master         |  
                            Master -> Production  

La mia regola generale è che nessun singolo cambiamento dovrebbe richiedere più di qualche ora. In tal caso, è necessario apportare modifiche minori. Se si tratta di un'enorme funzionalità (come una riscrittura dell'interfaccia utente), va a lungo termine in modo che lo sviluppo normale possa continuare allo stesso tempo. Le filiali LongTerm sono normalmente solo filiali locali mentre Sviluppo, Master e Produzione sono filiali remote. Anche tutti i rami secondari sono solo locali. Questo mantiene il repository pulito per gli altri, senza perdere l'utilità di git su un set di funzionalità a lungo termine.

Vorrei sottolineare, tuttavia, che l'esistenza di un ramo a lungo termine è una cosa rara. Normalmente, tutto il mio lavoro è in fase di sviluppo. Solo quando ho una funzione (impostata) che impiegherà così tanto tempo che devo essere in grado di lavorare anche su normali cose di sviluppo, uso il ramo LongTerm. Se è solo una serie di modifiche che dovrebbero essere insieme, allora non mi unirò al padrone fino a quando tutto non sarà fatto.


"Nelle principali funzioni (a lungo termine) creo una filiale dallo sviluppo" - non dovresti creare nuove filiali (sviluppo) dalla filiale di produzione? Visto che il ramo di produzione è un codice pronto per il rilascio.
robotron,

No, la produzione è già stata rilasciata, il master è in anticipo sulla produzione e lo sviluppo è in anticipo sul master. Una nuova funzionalità come aggiungere imposta ai totali degli ordini è inutile se non si lavora su un codice che ha già ordini.
Coteyr,

Ma se si ramifica da sviluppo e successivamente si fonde indietro, quel ramo (e di conseguenza master e produzione in seguito) incorporerà tutte le modifiche di sviluppo apportate da altri fino al punto di ramificazione? Alcune di queste modifiche potrebbero non avere l'approvazione del QA. Forse stavano parlando di diversi approcci per la gestione dei rilasci.
robotron,

Sì lo sarà, questo è il punto. Test di controllo qualità su un SHA specifico nel master, ma non puoi tenerlo sviluppato.
Coteyr,

"Test di controllo qualità su un SHA specifico nel master" -> Test di controllo qualità ogni nuova funzionalità come standalone? Lasciate che gestisca da voi uno scenario tipico che il mio team affronta: supponiamo che abbiate 2 progetti a lungo termine sulla stessa base di codice: il Progetto A è in QA per il mese scorso e sarà QA per un altro mese. Il progetto B è stato sviluppato negli ultimi 6 mesi ed è ora pronto per il controllo qualità. Il progetto A viene unito al master e sicuramente non è pronto per la produzione a causa di numerosi e impercettibili errori nelle regole di business. Come gestiamo il progetto B? A e B devono essere testati insieme per verificare le interazioni (B non causerà conflitti durante l'unione).
robotron,
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.