Ramificare o non ramificare?


84

Fino a poco tempo fa il mio flusso di lavoro di sviluppo era il seguente:

  1. Ottieni la funzionalità dal proprietario del prodotto
  2. Crea una diramazione (se la funzionalità è più di 1 giorno)
  3. Implementalo in un ramo
  4. Unisci le modifiche dal ramo principale al mio ramo (per ridurre i conflitti durante l'unione all'indietro)
  5. Unisci il mio ramo al ramo principale

A volte ci sono stati problemi con la fusione, ma in generale mi è piaciuto.

Ma recentemente vedo sempre più seguaci dell'idea di non creare filiali poiché rende più difficile praticare l'integrazione continua, la consegna continua, ecc. E suona particolarmente divertente da persone con background VCS distribuito che parlavano così tanto di grandi implementazioni di fusione di Git, Mercurial, ecc.

Quindi la domanda è: dovremmo usare le filiali al giorno d'oggi?


2
Sono sicuro che questa sia la piattaforma giusta per questo, ma sì, vorrei diramare. Ma forse dovresti pensare di fondere alcuni
ZeissS

1
Sembra che abbiano bisogno di strategie migliori per la fusione.
b01,

1
Ho sempre visto tutti gli commit come una fusione, anche se solo da locale a remoto. L'unione dai rami è la stessa, solo una serie di modifiche più ampia, quindi non capisco quale sia l'argomento in entrambi i casi. Qualcuno ha fatto una profilazione effettiva sulle prestazioni di una di queste tecniche o è solo un'ottimizzazione pre-matura?
Tylermac,

Direi che i rami renderebbero più semplice la CI ...
tdammers,

7
Si prega di non postare lo stesso post in modo incrociato su più siti di Exchange Stack.
Adam Lear

Risposte:


64

A meno che non si sta lavorando tutti dallo stesso albero di lavoro, che si sta utilizzando rami, se li chiami o no. Ogni volta che uno sviluppatore esegue il checkout nel suo albero di lavoro, crea un ramo di sviluppo locale separato e ogni volta che effettua il check-in fa una fusione. Per la maggior parte dei team, la domanda non è se si utilizzano filiali, le domande sono quante e per quale scopo ?

L'unico modo per fare un'integrazione veramente "continua" è che tutti possano lavorare sullo stesso albero di lavoro. In questo modo, sai immediatamente se le modifiche influiscono negativamente su quelle di qualcun altro. Ovviamente, è insostenibile. È necessario un certo grado di isolamento in un ramo per realizzare qualsiasi cosa, anche se quel "ramo" è solo la directory di lavoro locale. Ciò che serve è un giusto equilibrio tra integrazione e isolamento.

Nella mia esperienza, l'uso di più filiali migliora il grado di integrazione, poiché l'integrazione viene eseguita con precisione con le persone che devono essere fatte e tutti gli altri possono isolare più facilmente i problemi non correlati come richiesto.

Ad esempio, ho trascorso l'ultimo giorno a rintracciare tre bug relativi all'integrazione recentemente introdotti nella nostra build che stavano bloccando il mio lavoro "reale". Avendo fatto la mia dovuta diligenza nel segnalare questi bug alle persone che hanno bisogno di risolverli, ora devo solo aspettare che abbiano finito per continuare il mio lavoro? Ovviamente no. Ho creato un ramo locale temporaneo che ripristina tali modifiche in modo da poter disporre di una base di riferimento stabile su cui lavorare pur ricevendo le ultime modifiche dall'upstream.

Senza la possibilità di creare un nuovo ramo a tale scopo, sarei ridotto a una delle tre opzioni: ripristina le modifiche nel repository centrale, mantieni manualmente le patch che le ripristinano nel mio albero di lavoro e cerca di non controllarle accidentalmente o tornare a una versione prima dell'introduzione di tali bug. È probabile che la prima opzione interrompa un'altra dipendenza. La seconda opzione è molto impegnativa, quindi la maggior parte delle persone sceglie la terza opzione, che essenzialmente ti impedisce di fare più lavoro di integrazione fino a quando i bug trovati in precedenza non sono stati corretti.

Il mio esempio utilizzava una filiale locale privata, ma lo stesso principio si applica alle filiali condivise. Se condivido il mio ramo, allora forse altre 5 persone sono in grado di continuare con i loro compiti primari invece di svolgere un lavoro di integrazione ridondante, quindi in aggregato viene eseguito un lavoro di integrazione più utile. Il problema con la ramificazione e l'integrazione continua non è il numero di filiali che hai, è la frequenza con cui le unisci.


1
Se annulli i commit indesiderati nel tuo nuovo ramo, non li inverti nel ramo principale quando ti unisci in esso? Personalmente mi sarei ramificato da un punto prima delle modifiche indesiderate e avrei scelto le modifiche da cui dipendevo nel nuovo ramo.
Anthony,

@anthony Molto probabilmente, puliresti la tua cronologia (eliminerai i ripristini) prima di unirti. Qualcuno contro la riscrittura della storia probabilmente sta meglio seguendo il tuo metodo.
idbrii,

Se estrai le ramificazioni e riscrivi la cronologia, perché usare Git?
everton,

80

la domanda è: dovremmo usare le filiali al giorno d'oggi?

Bene, circa mezzo anno fa sono stato incaricato di eseguire uno studio per rispondere a questa domanda. Ecco il riassunto, basato sui riferimenti studiati (elencati di seguito)

  • non esiste una strategia di ramificazione "migliore" comunemente accettata applicabile a qualsiasi progetto
    • la maggior parte delle risorse sembra concordare sul fatto che la scelta della strategia produttiva dipende dalle specifiche specifiche del progetto
    • nota a margine. Sulla base di quanto sopra sembra che qualsiasi modifica alla strategia di diramazione del progetto debba essere testata, misurata e confrontata con altre opzioni testate
  • l'opinione popolare è che fondersi con Subversion richiede molti sforzi. Tutti coloro che hanno confrontato SVN e Git notano che la fusione è molto più semplice con Git
  • un fattore importante sembra essere se i rilasci di produzione provengono da tronchi o rami. Ai team che eseguono rilasci di produzioni da trunk (che sembrano non essere un modo abbastanza popolare) è essenzialmente vietato utilizzare una strategia trunk instabile . I team che realizzano rilasci di prodotti dalle filiali hanno più opzioni di ramificazione tra cui scegliere.
  • le strategie popolari sembrano essere tronco stabile, tronco instabile e ramo dello sviluppo (integrazione)

Riferimenti

  • http://msdn.microsoft.com/en-us/library/aa730834%28v=vs.80%29.aspx

    ... Decidere la migliore strategia di ramificazione è un atto di bilanciamento. È necessario compensare gli aumenti di produttività con un aumento del rischio. Un modo per convalidare una strategia scelta è considerare uno scenario di cambiamento. Ad esempio, se si decide di allineare i rami con l'architettura di sistema (ad esempio, un ramo rappresenta un componente di sistema) e si prevedono cambiamenti significativi nell'architettura, potrebbe essere necessario ristrutturare i rami e i processi e le politiche associati ad ogni cambiamento. La scelta di una strategia di ramificazione inadeguata può causare spese generali di processo e lunghi cicli di integrazione e rilascio che si rivelano frustranti per l'intero team ...

  • http://www.cmcrossroads.com/bradapp/acme/branching/

    ... Una frequente integrazione incrementale è una delle indicazioni del successo e la sua assenza è spesso una caratteristica del fallimento. Gli attuali metodi di gestione del progetto tendono ad evitare rigidi modelli a cascata e ad abbracciare i modelli a spirale di sviluppo iterativo / incrementale e consegna evolutiva. Le strategie di integrazione incrementale, come Merge Early e Often e le sue varianti, sono una forma di gestione del rischio che cerca di eliminare il rischio all'inizio del ciclo di vita quando c'è più tempo per reagire. La regolarità del ritmo tra le integrazioni è vista da [Booch], [McCarthy] e [McConnell] come un indicatore principale della salute del progetto (come un "impulso" o un "battito cardiaco").  
     
    L'integrazione precoce e frequente non solo rischia prima e in piccoli "pezzi" più piccoli, comunica anche i cambiamenti tra i compagni di squadra ...

  • http://www.codinghorror.com/blog/2007/10/software-branching-and-parallel-universes.html

    ... Nella maggior parte dei sistemi di controllo del codice sorgente, è possibile creare centinaia di filiali senza problemi di prestazioni; è il sovraccarico mentale di tenere traccia di tutti quei rami di cui devi davvero preoccuparti ... La ramificazione è una bestia complessa. Ci sono dozzine di modi per diramare e nessuno può davvero dirti se lo stai facendo nel modo giusto o sbagliato ...

  • http://www.lostechies.com/blogs/derickbailey/archive/2010/02/24/branching-strategies-when-to-branch-and-merge.aspx

    ... Ci sono molti aspetti di un sistema da considerare quando si ramifica il codice ... Alla fine, l'obiettivo è fornire un sandbox per il contesto in cui viene scritto il codice. Comprendere le opzioni disponibili, quando ciascuna opzione è più adatta alla situazione attuale e il costo di queste opzioni ti aiuterà a decidere come e quando ramificare ...

  • http://www.snuffybear.com/ucm_branch.htm
    Nota data altri riferimenti elencati qui, l'affermazione dell'autore secondo cui "Questo articolo descrive tre modelli di ramificazione chiave utilizzati nei progetti di ingegneria del software" non sembra giustificata. La terminologia utilizzata non sembra molto diffusa ( EFIX , Modello-1,2,3 ecc.).

  • http://svn.haxx.se/users/archive-2007-10/att-0101/SCMBranchingModels-talkback.pdf Il
    riferimento presenta un interessante esempio di difficoltà nel comunicare strategie di ramificazione.

  • http://simpleprogrammer.com/2010/06/04/simple-branching-strategy-part-1-back-to-basics/
    ... Mantieni la semplicità. Lavorare direttamente dal bagagliaio è di gran lunga l'approccio migliore secondo me.  
     
    Sembra quasi un'eresia quando lo scrivo davvero sul mio schermo, ma se mi sopporterai per un momento, non solo ti mostrerò perché penso sia essenziale per un processo Agile, ma ti mostrerò come per farlo funzionare ...  
     
    ... Se dovessi basare il mio ragionamento su un argomento solido, sarebbe il valore dell'integrazione continua. Ho scritto un blog sul valore dell'IC e delle migliori pratiche in passato. Sono un grande sostenitore di CI ...  
     
    ... Devi davvero farti una domanda qui: "Tutto il sovraccarico che stai affrontando nel fare la tua complicata strategia di ramificazione e fusione risulta in un valore reale che non esiste in una strategia più semplice?" ...  
     
    .. .Una strategia che ho effettivamente utilizzato in passato e che ho sviluppato nel tempo. Lo riassumo brevemente qui.

  • http://www.codelathe.com/blog/index.php/2009/07/02/a-svn-branching-strategy-that-works/
    ... Infine, ricorda che non esiste una strategia di ramificazione e fusione ideale. Dipende praticamente dal tuo ambiente di sviluppo unico ...

  • http://blog.perforce.com/blog/?cat=62
    ... Lo scenario peggiore è che si introduce un problema di "unione semantica", in cui il risultato di un'unione automatizzata non è corretto, ma viene compilato OK e passa di nascosto test, forse anche sopravvivere abbastanza a lungo da essere un bug visibile dal cliente. Eek!  
     
    Aggiungendo l'insulto al danno, poiché possono sfuggire più a lungo al rilevamento, i problemi di unione semantica sono più difficili da risolvere in seguito, poiché la modifica non è più fresca nella mente dello sviluppatore che ha originato la modifica. (Di solito è meglio unire le modifiche subito dopo averle apportate, idealmente dallo sviluppatore che ha originato la modifica se è pratico) ...

  • https://stackoverflow.com/questions/34975/branching-strategies I
    membri della community condividono esperienze diverse in vari progetti utilizzando varie strategie di branching. Nessun consenso concordato sul "migliore" o "peggiore".

  • http://www.stickyminds.com/s.asp?F=S16454_COL_2
    In sostanza un breve riassunto delle cose presentate in http://oreilly.com/catalog/practicalperforce/chapter/ch07.pdf

    • http://www.stickyminds.com/s.asp?F=S16511_COL_2
      ... Esistono tre approcci comuni per decidere quando e come ramificare:
      • Crea il ramo di rilascio quando hai completato la funzione e pianifica di risolvere i problemi dell'ultimo minuto su questa riga di codice. In questo caso, il ramo di rilascio è in realtà una "riga di codice di preparazione rilascio", come descritto in Modelli di gestione della configurazione del software , poiché ci si aspetta che ci sia ancora del lavoro da fare.
      • Cambia il tuo stile di lavoro per evitare il lavoro di integrazione finale, lavorando al di fuori della linea di sviluppo attiva.
      • Diramazione per il nuovo lavoro creando un ramo di attività e unendo tale lavoro nella linea di sviluppo attiva al termine del rilascio.
        ... Una logica per la ramificazione è quella di isolare il codice alla fine di una versione in modo che possa stabilizzarsi. L'isolamento attraverso la ramificazione spesso maschera un problema di qualità che finirà per manifestarsi nel costo aggiuntivo di mantenere flussi paralleli prima che un prodotto venga rilasciato. La ramificazione è facile. Piuttosto, è la fusione e l'overhead cognitivo di comprendere come i cambiamenti fluiscono tra i rami che sono difficili, quindi è importante scegliere un processo che minimizzi i costi di ramificazione e fusione ...
  • http://nvie.com/posts/a-successful-git-branching-model/ Strategia orientata al Git.
    ... Consideriamo origin / master il ramo principale in cui il codice sorgente di HEAD riflette sempre uno stato pronto per la produzione .  
     
    Consideriamo origine / sviluppo come il ramo principale in cui il codice sorgente di HEAD riflette sempre uno stato con le ultime modifiche di sviluppo fornite per la prossima versione. Alcuni chiamerebbero questo "ramo di integrazione". Qui è dove vengono costruite tutte le build notturne automatiche ....

  • http://svnbook.red-bean.com/en/1.5/svn.branchmerge.html
    ... le politiche del progetto variano ampiamente riguardo esattamente quando è appropriato creare un ramo di funzionalità. Alcuni progetti non usano mai i rami delle funzionalità: gli commit in / trunk sono gratuiti. Il vantaggio di questo sistema è che è semplice: nessuno ha bisogno di conoscere ramificazioni o fusioni. Lo svantaggio è che il codice trunk è spesso instabile o inutilizzabile. Altri progetti utilizzano le filiali all'estremo: nessun cambiamento viene mai impegnato direttamente nel trunk. Anche i cambiamenti più banali vengono creati su un ramo di breve durata, attentamente rivisti e uniti al tronco. Quindi il ramo viene eliminato. Questo sistema garantisce un tronco eccezionalmente stabile e utilizzabile in ogni momento, ma a costo di tremendoprocesso in testa.  
     
    La maggior parte dei progetti ha un approccio a metà strada. Normalmente insistono sul fatto che / trunk compili e superi i test di regressione in ogni momento. Un ramo di funzionalità è richiesto solo quando una modifica richiede un numero elevato di commit destabilizzanti. Una buona regola empirica è quella di porre questa domanda: se lo sviluppatore ha lavorato per giorni in isolamento e quindi ha eseguito il grande cambiamento tutto in una volta (in modo che / trunk non fosse mai destabilizzato), sarebbe un cambiamento troppo grande da rivedere? Se la risposta a questa domanda è "sì", la modifica dovrebbe essere sviluppata su un ramo di funzionalità. Poiché lo sviluppatore apporta modifiche incrementali al ramo, possono essere facilmente rivisti dai peer.  
     
    Infine, c'è il problema di come mantenere un ramo di funzionalità in "sincronizzazione" con il trunk man mano che il lavoro procede. Come accennato in precedenza, esiste un grande rischio di lavorare su una filiale per settimane o mesi; i cambiamenti del tronco possono continuare a riversarsi, al punto in cui le due linee di sviluppo differiscono così tanto che può diventare un incubo nel tentativo di ricongiungere il ramo al tronco.  
     
    È preferibile evitare questa situazione unendo regolarmente le modifiche del trunk al ramo. Prepara una politica: una volta alla settimana, unisci le modifiche del tronco dell'ultima settimana al ramo ...

  • http://thedesignspace.net/MT2archives/000680.html
    ... Questa sezione dell'esercitazione CVS di Eclipse si basa sull'articolo di Paul Glezen sul sito Web di Eclipse: Branching con Eclipse e CVS e viene utilizzata con la sua autorizzazione secondo i termini di la licenza EPL. Le modifiche che sto apportando alla sua versione sono principalmente per espanderlo con più immagini e spiegazioni passo-passo e integrarlo con i miei tutorial per principianti nel tentativo di renderlo più accessibile a principianti e designer. Gli sviluppatori esperti preferiranno probabilmente lavorare dalla versione di Paul ...

  • http://learnsoftwareprocesses.com/2007/12/29/common-branching-strategies/
    ... Ecco alcuni dei modelli di ramificazione comuni:  

    1. Modello di filiale per versione: una delle strategie di ramificazione più comuni è quella di allineare le filiali con le versioni del prodotto. Una filiale detiene tutte le risorse di sviluppo software per una singola versione. Occasionalmente, gli aggiornamenti devono essere uniti da una versione all'altra, ma di solito non si fondono mai. Le filiali verranno interrotte quando viene ritirata una versione.  
    2. Filiale per promozione: un altro approccio molto comune è quello di allineare le filiali con i livelli di promozione degli asset software. Una versione di sviluppo specifica è ramificata in un ramo di test, in cui vengono eseguiti tutti i test di integrazione e di sistema. Quando si completano i test, le risorse di sviluppo software vengono diramate nel ramo di produzione e infine distribuite.  
    3. Filiale per attività: per evitare sovrapposizioni di attività (o attività) e una perdita di produttività, è possibile isolarle su una filiale separata. Tieni presente che si tratta di filiali a breve termine che dovrebbero essere unite non appena l'attività è stata completata, altrimenti lo sforzo di fusione richiesto potrebbe superare i vantaggi in termini di produttività della loro creazione in primo luogo.  
    4. Ramo per componente: è possibile allineare ciascun ramo con l'architettura di sistema. In questa strategia, si ramificano singoli componenti (o sottosistemi). Quindi ogni team che sviluppa un componente decide quando unire nuovamente il proprio codice nella linea di sviluppo che funge da ramo di integrazione. Questa strategia può funzionare bene se è presente l'architettura di sistema e i singoli componenti hanno interfacce ben definite. Il fatto che si sviluppino componenti sulle filiali consente un controllo più approfondito sugli asset di sviluppo software.  
    5. Branch per tecnologia: un'altra strategia di branching allineata con l'architettura di sistema. In questo caso i rami sono allineati alle piattaforme tecnologiche. Il codice comune è gestito su un ramo separato. A causa della natura unica delle risorse di sviluppo software gestite nelle filiali, probabilmente non si fondono mai ...
  • http://msdn.microsoft.com/en-us/library/bb668955.aspx
    ... Fare riferimento alle linee guida per la ramificazione e l'unione in "Linee guida per il controllo del codice sorgente" in questa guida per un riepilogo delle linee guida per la ramificazione e l'unione. ... Quando si ramificano, considerare quanto segue:

    • Non diramare a meno che il team di sviluppo non debba lavorare sullo stesso set di file contemporaneamente. Se non sei sicuro, puoi etichettare una build e creare un ramo da quella build in un secondo momento. La fusione dei rami può richiedere molto tempo e essere complessa, soprattutto se vi sono cambiamenti significativi tra loro.
    • Strutturare i rami in modo che sia necessario unirli solo lungo la gerarchia (su e giù per il ramo) anziché attraverso la gerarchia. La ramificazione nella gerarchia richiede l'utilizzo di un'unione senza fondamento, che richiede una risoluzione manuale dei conflitti più ampia.
    • La gerarchia del ramo si basa sul ramo padre e sul ramo figlio, che possono essere diversi dalla struttura fisica del codice sorgente sul disco. Quando pianifichi le fusioni, tieni presente la struttura del ramo logico piuttosto che la struttura fisica sul disco.
    • Non ramificarti troppo in profondità. Poiché è necessario del tempo per eseguire ciascuna unione e risolvere i conflitti, una struttura di diramazione profonda può significare che i cambiamenti in un ramo figlio potrebbero richiedere molto tempo per propagarsi al ramo principale. Ciò può influire negativamente sulle pianificazioni del progetto e aumentare il tempo necessario per correggere i bug.
    • Branch ad alto livello e include i file di configurazione e di origine.
    • Fai evolvere la tua struttura ramificata nel tempo.
    • La fusione richiede che uno o più sviluppatori eseguano l'unione e risolvano i conflitti. L'origine unita deve essere accuratamente testata perché non è raro prendere decisioni di fusione errate che possono destabilizzare la build.
    • La fusione nella gerarchia delle filiali è particolarmente difficile e richiede la gestione manuale di molti conflitti che potrebbero altrimenti essere gestiti automaticamente.  
      La decisione di creare una succursale può essere ridotta al fatto che il costo della fusione dei conflitti in tempo reale sia superiore al costo generale della fusione dei conflitti tra filiali ...
  • http://kashfarooq.wordpress.com/2009/11/23/bazaar-branching-strategy-with-a-subversion-trunk/

  • http://social.msdn.microsoft.com/Forums/en/tfsversioncontrol/thread/f127676c-8f05-410c-9a30-0eb43a26a9fa
    discussione delle migliori pratiche per la strategia del ramo di isolamento del rilascio nel caso di sistemi in evoluzione.

  • http://branchingguidance.codeplex.com/
    "Guida alle ramificazioni di Microsoft Team Foundation Server": documento dettagliato e dettagliato con raccomandazioni su misura per diversi progetti: versione HTML qui . È stato dimostrato che Microsoft non crede nelle strategie di ramificazione wrt su misura unica.

  • https://stackoverflow.com/questions/597707/best-branching-strategy-when-doing-continuous-integration
    Qual è la migliore strategia di branching da utilizzare quando si desidera effettuare l'integrazione continua? ... La risposta dipende dalle dimensioni del team e dalla qualità del controllo del codice sorgente e dalla possibilità di unire correttamente set di modifiche complessi ...

  • http://codicesoftware.blogspot.com/2010/03/branching-strategies.html
    ... CVS e SVN stavano scoraggiando l'intera strategia di ramificazione / fusione poiché non erano totalmente in grado di farlo ... ... Regola semplice: crea un ramo di attività per ogni nuova funzionalità o correzione di bug che devi implementare ... Può sembrare eccessivo per gli utenti SVN / CVS ma sai che qualsiasi SCM moderno ti permetterà di creare rami in un secondo, quindi non c'è un vero sovraccarico.  
     
    Nota importante: se lo guardi attentamente vedrai che sto parlando dell'uso di rami di attività come elenchi di modifiche per ricchi ...

  • http://publib.boulder.ibm.com/infocenter/cchelp/v7r0m1/index.jsp?topic=/com.ibm.rational.clearcase.cc_proj.doc/c_bntr_plnbrstrat.htm
    ... La politica di ramificazione è influenzata dallo sviluppo obiettivi del progetto e fornisce un meccanismo per controllare l'evoluzione della base di codice. Esistono tante varianti della politica di diramazione quante sono le organizzazioni che utilizzano il controllo versione di Rational ClearCase. Ma ci sono anche somiglianze che riflettono l'adesione comune alle migliori pratiche ...

  • http://blogs.open.collab.net/svn/2007/11/branching-strat.html
    ... Il modello Subversion (o modello open source generale in modo più accurato) è ciò che viene mostrato nel modello trunk instabile. .

  • http://en.wikipedia.org/wiki/Trunk_%28software%29
    Nel campo dello sviluppo del software, trunk si riferisce al ramo (versione) senza nome di un albero di file sotto controllo di revisione . Il tronco di solito è pensato per essere la base di un progetto su cui progredisce lo sviluppo. Se gli sviluppatori lavorano esclusivamente sul trunk, contiene sempre l'ultima versione all'avanguardia del progetto, ma potrebbe anche essere la versione più instabile. Un altro approccio è quello di dividere un ramo dal tronco, implementare le modifiche in quel ramo e unire nuovamente le modifiche nel tronco quando il ramo si è dimostrato stabile e funzionante. A seconda della modalità di sviluppo e del commitpolitica il trunk può contenere la versione più stabile o la meno stabile o qualcosa nel mezzo.  
     
    Spesso il lavoro dello sviluppatore principale si svolge nel trunk e le versioni stabili sono ramificate e le correzioni di bug occasionali vengono unite dai rami al trunk. Quando lo sviluppo di versioni future viene eseguito in rami non trunk, di solito viene eseguito per progetti che non cambiano spesso o in cui si prevede che un cambiamento impiegherà molto tempo a svilupparsi fino a quando non sarà pronto per essere incorporato nel trunk. .

  • http://www.mcqueeney.com/roller/page/tom/20060919
    ... Queste sono le note di un webinar sulle migliori pratiche di Subversion , condotto il 30 agosto 2006 da CollabNet. ... Due strategie organizzative: tronco instabile vs. tronco stabile ... ... PREFERISCI un tronco instabile quando possibile ...

  • https://stackoverflow.com/questions/153812/subversion-is-trunk-really-the-best-place-for-the-main-development
    In SVN, trunk è il posto consigliato per lo sviluppo principale e utilizzo questa convenzione per tutti i miei progetti. Tuttavia, ciò significa che a volte il trunk è instabile o addirittura rotto ... ... non sarebbe meglio fare lo "sviluppo selvaggio" su un ramo come / branch / dev e fondersi con il trunk solo quando la build è ragionevolmente solido?

    • ... Il tronco è dove dovrebbe avvenire lo sviluppo in corso. Non dovresti davvero avere problemi con il codice "rotto", se tutti stanno testando le loro modifiche prima di eseguirle. Una buona regola empirica è fare un aggiornamento (ottenere tutto il codice più recente dai repository) dopo aver codificato le modifiche. Quindi compilare ed eseguire alcuni test unitari. Se tutto si sviluppa e funziona, dovresti essere bravo a controllarlo in ...
    • ... No tronco non è il posto migliore. Nella nostra organizzazione seguiamo sempre questo approccio: Trunk contiene il codice di rilascio, quindi viene sempre compilato. Con ogni nuovo rilascio / pietra miliare apriamo una nuova filiale. Ogni volta che uno sviluppatore possiede un articolo, crea un nuovo ramo in questo ramo di rilascio e lo unisce in un ramo di rilascio solo dopo averlo testato. Il ramo di rilascio viene unito nel trunk dopo il test del sistema ...
  • http://blog.yclian.com/2009/03/working-on-branches-and-stable-trunk.html
    ... Lavoravo sul bagagliaio perché per tutti i progetti a cui ho lavorato, o lo ero l'unico sviluppatore o il team ha assicurato che tutti i check-in del codice hanno superato i test locali. Altrimenti, abbiamo creato (ancora) rami per correzioni di bug, codice di grandi dimensioni per nuove funzionalità, ecc.  
     
    Circa 2 mesi fa, ho avuto una breve sessione git con Kamal e ha condiviso con me l'idea di storia / ramo . E quando la mia squadra ha iniziato a crescere con più ragazzi di sviluppo, sento il bisogno di incoraggiare una maggiore ramificazione e ora questa è diventata una regola. Per un progetto con test automatizzati definiti con configurazione CI, è garantito un trunk stabile e questa pratica può adattarsi molto bene ad esso.  
     
    Non usiamo git ma Subversion perché è così che abbiamo iniziato e ora ci sentiamo ancora a nostro agio (la maggior parte delle volte) ...

  • http://www.ericsink.com/scm/scm_branches.html
    Questo fa parte di un libro online chiamato Source Control HOWTO , una guida delle migliori pratiche sul controllo del codice sorgente, controllo della versione e gestione della configurazione ...  
     
    ... Eric's Preferred Branching Allenati ... Mantieni un tronco "sostanzialmente instabile". Esegui il tuo sviluppo attivo nel bagagliaio, la cui stabilità aumenta quando ti avvicini al rilascio. Dopo la spedizione, crea un ramo di manutenzione e mantienilo sempre molto stabile ...  
     
    ... Nel prossimo capitolo approfondirò l'argomento della fusione dei rami ...

  • http://marc.info/?l=forrest-dev&m=112504297928196&w=2
    Avvio della posta del thread che discute le strategie di ramificazione per il progetto Apache Forrest

    • si noti che al momento il progetto sembra utilizzare un modello di trunk instabile con rami di rilascio:
    • "Il lavoro di sviluppo viene eseguito sul trunk di SVN ... Esistono" rami di rilascio "di SVN, ad esempio forrest_07_branch." ( linee guida del progetto )
    • "Creazione dei pacchetti candidati al rilascio ... 17. Creare un ramo di manutenzione in SVN ..." ( Come rilasciare )
  • Documenti ramificati di O'Reilly CVS:
    http://commons.oreilly.com/wiki/index.php/Essential_CVS/Using_CVS/Tagging_and_Branching#Basically_stable

    • ... La filosofia di diramazione sostanzialmente stabile afferma che il trunk dovrebbe contenere dati di progetto che sono quasi sempre pronti per il rilascio ... ... Variazioni più indulgenti di questa filosofia consentono a tutto ciò che supera i test unitari degli sviluppatori di essere uniti nel tronco. Un approccio così rilassato richiede che un candidato di rilascio sia ramificato e sottoposto a un'analisi di qualità completa prima della pubblicazione ...
    • ... La filosofia sostanzialmente instabile afferma che il trunk dovrebbe contenere l'ultimo codice, indipendentemente dalla sua stabilità, e che i candidati al rilascio dovrebbero essere diramati per il controllo qualità.
       
       
      ... Altre variazioni indulgenti consentono anche la diramazione di codice sperimentale, refactoring e altri codici di casi speciali. L'unione di un ramo nel tronco viene eseguita dai gestori del ramo. ...
      • Nota la risorsa sopra non è stata visualizzata in nessuna delle ricerche che ho eseguito (le linee guida relative a CVS non sono più popolari?)
  • Le migliori pratiche in SCM (articolo di approfondimento) su
    http://www.perforce.com/perforce/papers/bestpractices.html
    ... sei aree generali di implementazione di SCM e alcune best practice a grana grossa all'interno di ciascuna di quelle aree. I seguenti capitoli spiegano ogni elemento ...
    Aree di lavoro, Codeline, Branching, Propagazione del cambiamento, Build, Processo ...


37
Credo che sia la risposta più lunga che abbia mai visto in qualsiasi domanda su stackexchange!
John Fisher,

2
@JohnFisher secondo JIRA , allora ho passato 6 ore a compilare e sintetizzare questi riferimenti :)
moscerino

2
Ti manca una sorta di riepilogo, che dovrebbe indicare se utilizzare o meno nuovi rami per le nuove funzionalità. La tua risposta è solo una somma di collegamenti a vari articoli: alcuni raccontano una cosa, mentre altri dicono esattamente il contrario. La tua risposta è piuttosto lunga, quindi potrei essermi perso.
BЈовић,

3
Il riassunto di @ BЈовић è fornito all'inizio della risposta: 'non esiste una strategia di ramificazione "migliore" comunemente accettata applicabile a qualsiasi progetto. * la maggior parte delle risorse sembra concordare sul fatto che la scelta della strategia produttiva dipende dalle specifiche specifiche del progetto '
moscerino

2
lettura supplementare: sviluppo basato su trunk di Google vs Facebook "Loro [Google e Facebook] non hanno problemi di unione, perché di norma gli sviluppatori non si stanno unendo alle / dalle filiali. Almeno fino al server del repository centrale non lo sono. Sulle stazioni di lavoro , gli sviluppatori potrebbero unirsi a / da filiali locali e riequilibrare quando la spinta di qualcosa che "ha fatto" torna al repository centrale ... "
moscerino

7

Se hai diversi team che lavorano contemporaneamente su funzionalità diverse, non puoi in alcun modo omettere la ramificazione. Dovresti condividere il codice (parzialmente implementato) con i membri del team, impedendo ad altri team di ottenere le tue funzionalità non finite.

I rami sono il modo più semplice per raggiungere questo obiettivo.

Sebbene sia utile abbreviare il ciclo di vita dei rami ed evitare di lavorare sullo stesso modulo in due rami contemporaneamente - non avrai conflitti \ problemi.


5

Ma recentemente vedo sempre più seguaci dell'idea di non creare filiali in quanto rende più difficile praticare l'integrazione continua, la consegna continua, ecc.

Bene vuol rendere più difficile da praticare l'integrazione continua, erogazione continua, ecc per voi concretamente?

In caso contrario, non vedo alcun motivo per cambiare il tuo modo di lavorare.

Naturalmente, è buona prassi seguire cosa sta succedendo e come si evolvono le migliori pratiche attuali. Ma non credo che dovremmo abbandonare i nostri processi / strumenti / quant'altro solo perché X (e / o Y e / o Z) hanno detto che non sono più di moda :-)


Certo che lo fa! È la questione delle priorità: ramificazione (isolamento delle caratteristiche) vs. facile integrazione, consegna, ecc.
SiberianGuy

1
è solo una questione di strumento CI che stai usando. Cosa ti impedisce di fare build e "consegnare continuamente" da un ramo?
Shaddix,

@Shaddix, di solito è difficile consegnare dalla filiale. Ad esempio, come consegneresti dalla filiale delle caratteristiche?
SiberianGuy,

1
Qual è il problema, se hai tutto il codice sorgente ramificato (come in DVCS)?
Shaddix,

1
@Shaddix, più codice hai ramificato, più conflitti otterrai durante la fusione
SiberianGuy

4

Che interessante serie di risposte. In oltre 20 anni non ho mai lavorato in un'azienda che ha fatto un uso più che banale delle filiali (in genere solo per le filiali).

La maggior parte dei posti in cui ho lavorato si basano su check-in abbastanza rapidi e rilevamento / risoluzione rapidi delle collisioni: la metodologia Agile insegna che puoi risolvere i problemi più rapidamente se li noti mentre entrambe le parti stanno attivamente pensando a quel pezzo di codice.

D'altra parte, non ho usato git molto e forse è l'inclusione del tag git che ha influenzato queste risposte - capisco che branch / merge è un dato di fatto con git perché è così facile.


2
+1, Questi git'er dunn stanno diventando sempre più fanatici della discutibile superiorità di git rispetto ad altre configurazioni di controllo versione / CI.
maple_shaft

3

Sì, dovresti usare i rami per isolare qualsiasi sforzo di sviluppo (almeno medio). Vedi " Quando dovresti diramare? ".

Il problema riguarda soprattutto le fusioni a avanzamento rapido (che includono una cronologia delle succursali all'interno di un'altra), a condizione che prima si comprimano tutti i "commit intermedi del checkpoint" (che può essere un problema in caso di rollback o git bisect).
Vedere " Comprensione del flusso di lavoro di Git ", al fine di distinguere le filiali private (non destinate a essere inviate) dalle filiali pubbliche, che saranno completate da fusioni ff (fusioni con avanzamento rapido) a condizione che si effettui la pulizia necessaria all'interno della filiale che si sta unendo .
Vedi anche " Perché Git usa la fusione rapida per impostazione predefinita? ".


2

Dovresti assolutamente usare i rami. Ci sono molti punti di forza in questo.

  • Puoi controllare il tuo lavoro mentre sei preoccupato di perdere lavoro a causa di guasti HD, perdita di laptop ecc. E non si romperà il CI principale.
  • Puoi ancora fare CI, basta impostare il tuo CI locale per guardare la tua filiale.
  • Se la funzione viene improvvisamente messa in attesa (ciò non accade mai) puoi semplicemente parcheggiarla.

Troppo difficile non è mai una scusa. Ci vuole sempre più sforzo per farlo bene.


2
Voglio sottovalutare questo non perché sono contrario alle ramificazioni ma perché suggerisci che dovrebbero essere usate TUTTO IL TEMPO.
maple_shaft

Dove l'ha detto, l'ha modificato o qualcosa del genere?
b01,

imposta il tuo CI locale per controllare i tuoi rami per brevi periodi (2-5 giorni) che potrebbero essere piuttosto un sovraccarico. Ci sono stato fatto
moscerino

1
Stavo rispondendo alla domanda sull'uso dei rami in generale o praticamente mai usando i rami. Come in ogni norma o politica, dovrebbe entrare in gioco il buon senso. Non collaboro in molti dei miei progetti, ma uso ancora in modo liberale le filiali principalmente per il terzo proiettile che ho citato. Anche per quanto riguarda il primo proiettile, quante volte hai ricevuto una richiesta urgente per ottenere alcune funzionalità / correzioni dal vivo, ma poi entri e hai circa 3 funzioni complete a metà in master.
Bill Leeper,

Questo non sta facendo CI. Io in CI sono sinonimo di integrazione, integrando il lavoro di tutti gli sviluppatori, ovvero la fusione. Nulla di sbagliato nell'esecuzione di test in locale per ogni commit, ma è la stessa cosa.
bdsl,

2

Se due team lavorano nel proprio ramo, non vedranno i cambiamenti dell'altro team, anche se entrambi integrano il masterramo. Ciò significherebbe che i loro rami di sviluppo andranno alla deriva e se uno dei team si fonde con masterl'altro, l'altro team deve rifare molti cambiamenti.

Quindi, anche se hai filiali per le funzionalità, ti esorto a fare "backport" di tutti i refactoring al ramo master e mantenere il ramo solo per le nuove funzionalità.

  • Rifattorizzazioni backport

Penso che a volte potrebbe essere più semplice utilizzare gli switch di funzionalità per disabilitare nuove funzionalità non testate che non dovrebbero ancora essere messe in produzione. In questo modo tutte le altre squadre vedranno i cambiamenti e non dovrà avvenire alcuna fusione di big bang.

  • Usa gli interruttori di funzionalità

2

Abbiamo appena affrontato questo (di nuovo) .. Innanzitutto abbiamo avuto l'intero dibattito GIT / SVN, che ci ha portato a strategie di ramificazione in generale.

Le aziende più grandi utilizzano tutte una strategia basata sul trunk, in cui tutti lavorano nello stesso ramo e da quel ramo avvengono build e integrazione continua. Evitare i conflitti viene fatto utilizzando la modularizzazione del codice, la commutazione delle funzioni e strumenti intelligenti. Sembra difficile ... perché lo è. Ma se stai discutendo è perché sei caduto vittima delle fantasie delle persone sulla ramificazione. Alcuni sostengono di utilizzare qui lo strumento di inserimento SCM con un meccanismo di ramificazione promozionale completamente conforme a sarbanes-oxley, ed è tutto geniale. O mentono, si prendono in giro da soli o non lavorano sulla stessa scala di sistema che stai.

Ramificarsi e fondersi è difficile. Soprattutto se hai un'attività che cambia regolarmente idea e richiede rollback, ecc.

Questa frase può salvarti la vita: ciò che è nell'SCM non è lo stesso di ciò che è nei tuoi artefatti costruiti!

Se hai problemi con la ramificazione è perché stai usando male il tuo SCM. Lo facciamo da anni. È presente un sistema in cui SCM viene utilizzato per determinare ciò che va nella build finale.

Questo non è il lavoro di SCM. SCM è un file server glorificato. Il compito di determinare quali file del tuo SCM vanno inseriti nella tua build appartiene ai tuoi strumenti di build.

Il modulo A è in fase di elaborazione e verrà pubblicato nel rilascio settimanale. Il modulo B è il modulo A ma con il progetto X al suo interno, e su cui si sta lavorando, nello stesso ramo, ma non è stato incorporato nella versione. Ad un certo punto in futuro vuoi rilasciare il progetto X. Quindi dici al tuo strumento di costruzione di smettere di inserire il modulo A e iniziare a inserire il modulo B.

Ci saranno un sacco di pianti e strilli delle mani su questo. Che iffery e ululato generale. Tale è il livello di emozione che circonda qualcosa di semplice come un repository di file, non importa quanto intelligente.

Ma c'è la tua risposta.


1

Il problema principale con la ramificazione è la difficoltà di ricollegarsi alla filiale principale al termine dello sviluppo. La fusione può essere un processo manuale e soggetto a errori, pertanto dovrebbe essere evitato il più delle volte.

Alcune notevoli eccezioni in cui preferisco la ramificazione sono il refactoring massiccio, le funzionalità giganti che richiedono più tempo di uno sprint per lo sviluppo o le funzionalità dirompenti che potrebbero interrompere lo sviluppo di altre funzionalità durante la maggior parte di quello sprint.


4
Sembra che tu abbia bisogno di una pratica migliore per lo sviluppo di nuove funzionalità. Personalmente mi piace costruire i miei progetti in modo che sia facile isolare le funzionalità, di solito in un file / classe / o separato. In questo modo l'aggiunta o la rimozione di codice non causa grosse interruzioni nella consegna o problemi durante l'unione in un nuovo codice o l'estrazione di vecchio codice. Funziona bene anche in fase di sviluppo con più sviluppatori. Ma posso capire se stai lavorando a un progetto che potrebbe non essere stato avviato da te o se non hai una vera voce in capitolo su come il progetto continua.
b01,

1
@ b01, questo è praticamente perfetto. Nessuno può trovare il design perfetto quando i requisiti vanno avanti e indietro e cambiano più velocemente di un bambino ADHD in crack. Altre volte si finisce per provare a refactoring del codice legacy per migliorare il design e questa situazione si presenta di volta in volta. Non è il peggior problema che una squadra possa avere, ed è di gran lunga migliore rispetto ad alcuni posti in cui ho lavorato, anche se suggerire che il refactoring in una riunione ti farà battere a morte con una mazza da baseball come una scena degli Intoccabili.
maple_shaft

Totalmente in disaccordo. Se dividi per rami di qualità e ti unisci frequentemente (ogni giorno è buono), eviti quasi tutte le fusioni "manuali e soggette a errori".
Paul Nathan,

@Paul, fidati di me che non funziona per tutti i progetti o tecnologie. Pensa a un file di configurazione XML comune come in Struts in cui tutti ci immergono le mani ogni giorno. Ma no, la tua strada funziona sempre e mi sono totalmente meritato il voto negativo. Grazie.
maple_shaft

1
Il meta-suggerimento di @maple_shaft, se si considerano i tag (git) e si pubblica qualcosa che l'utente tipico di quei tag considererebbe negativo, si aspettano downvotes flyby. I flybys sono quasi sempre una reazione ingiustificata all'essere feriti da un commento che prendi personalmente. Consideralo buono perché aumenta il tuo rappresentante attraverso il tetto.
Bill K,

1

Raccomando questo tipo di schema di filiali:

rilascio - test - sviluppo

Quindi dallo sviluppo, ramo per sviluppatore e / o per funzione.

Ciascuno degli sviluppatori ha un ramo con cui giocare, e da cui fondersi, e poi nel ramo di sviluppo di routine - idealmente ogni giorno (fornendo compilazioni).

Questo tipo di schema funziona davvero bene con molti sviluppatori e progetti multipli sulla stessa base di codice.


0

Noi facciamo utilizzare i rami, ma non a livello granulare di funzionalità. Usiamo i rami per ogni sprint. La ramificazione in sostanza non è una cosa negativa dell'IMO, perché simula il concetto di SOC nella funzione o nel livello di sprint. Puoi facilmente riconoscere e gestire quale ramo appartiene a quale caratteristica o sprint.

IMHO, quindi la risposta è . Dovremmo ancora usare la ramificazione.


0

Il processo presso la mia organizzazione fa ampio uso delle filiali e (un processo che assomiglia un po ') alla continua integrazione.

Ad un livello elevato, gli sviluppatori non si preoccupano troppo della fusione con mainline, si limitano a impegnarsi nella filiale. un processo (semi) automatizzato verifica quali funzionalità sono programmate per essere messe in linea, unisce le filiali e crea il prodotto. Il processo funziona perché in realtà integriamo questo processo di fusione dal tracker dei problemi, in modo che lo strumento di creazione sappia quali rami unire.


Questo processo sembra interrompersi se uno sviluppatore ha eseguito il refactoring di un codice preesistente su un ramo e uno sviluppatore su un ramo separato ha scritto qualcosa che si basa sulla vecchia versione del codice.
bdsl,

@bdsl: questo è un problema che può sorgere in qualsiasi strategia di ramificazione (inclusa la non ramificazione), ogni volta che hai più sviluppatori nella stessa base di codice. in quella organizzazione (da allora sono passato), eravamo una squadra abbastanza piccola che tutti avevamo una buona idea di cosa stavano facendo gli altri, quindi ci avvertivamo quando è probabile che alcuni dei nostri cambiamenti fossero in conflitto. In ogni caso, l'integrazione continua ha aiutato moltissimo a individuare questo tipo di problemi entro pochi minuti o ore dall'introduzione del conflitto.
SingleNegationElimination,

Sì, ma sembra molto meno probabile se il refactoring viene unito alla mainline lo stesso giorno in cui è stato eseguito, piuttosto che attendere fino a quando una nuova funzionalità è pronta.
bdsl

@bdsl non è sempre un'opzione; potrebbe essere necessario un "buon ramo funzionante" in ogni momento, ad esempio per inviare correzioni di bug di emergenza. La tecnica alternativa, che unisce la linea principale alla funzione su base regolare, di solito è A-OK, e la mia forte raccomandazione non importa quale sia la tua strategia di ramificazione.
SingleNegationElimination,
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.