Domanda

Questa mattina ho letto due opinioni sul refactoring.

  • Parere 1 (Pagina non presente)
  • Parere 2 (Pagina non presente)

Raccomandano di ramificare (e successivamente unire) il codice in:

  1. Mantieni pulito il bagagliaio.
  2. Consenti a uno sviluppatore di abbandonare le modifiche rischiose.

Nella mia esperienza (in particolare con StarTeam di Borland), la fusione è un'operazione non trivalente. E per questo motivo, mi dirigo solo quando devo (cioè quando voglio congelare un candidato al rilascio).

In teoria, la ramificazione ha un senso, ma i meccanismi della fusione la rendono un'operazione molto rischiosa.

Le mie domande:

  
      
  • Ti senti a tuo agio nel fondere il codice?
  •   
  • Si ramifica il codice per motivi diversi dal congelamento di una versione   candidato?
  •   
È stato utile?

Soluzione

Alcuni principi guida sciolti:

  • Branch in ritardo e solo quando è necessario
  • Unisci presto e spesso
  • Ottieni la persona giusta per eseguire l'unione, la persona che ha apportato le modifiche o la persona che ha scritto la versione originale sono le migliori

La ramificazione è solo un altro strumento, devi imparare come usarlo in modo efficace se vuoi il massimo beneficio.

Il tuo atteggiamento nei confronti delle ramificazioni dovrebbe probabilmente differire tra progetti open source distribuiti (come quelli su Git) e progetti di sviluppo della tua azienda (possibilmente in esecuzione su SVN). Per i progetti distribuiti ti consigliamo di incoraggiare le ramificazioni per massimizzare l'innovazione e la sperimentazione, per quest'ultima varietà avrai bisogno di un controllo più rigoroso e di dettare le politiche di check-in per ogni riga di codice che detta quando la ramificazione dovrebbe / non dovrebbe avvenire, principalmente per " proteggere " ; il codice.

Ecco una guida alla ramificazione:
http://www.vance.com/steve/perforce/Branching_Strategies.html

Ecco una guida più breve con alcune best practice di alto livello:
https: //www.perforce. com / sites / default / files / pdf / alto livello per forza-best-practices.pdf

Altri suggerimenti

Le ramificazioni potrebbero essere dolorose ma non dovrebbero esserlo.

Ecco cosa ci dicono i progetti git-like (mercurial, bazar) su CVS e SVN. Su git e mercurial, la ramificazione è facile. Su SVN è facile ma con grandi progetti può essere un po 'difficile da gestire (a causa del tempo speso nel processo di ramificazione / fusione che può essere molto lungo - rispetto ad altri come git e mercurial - e difficile se non ci sono conflitti apparenti). Ciò non aiuta gli utenti che non sono abituati a ramificarsi spesso per avere fiducia nella ramificazione. Molti utenti ignari dei potenti usi delle ramificazioni, lo tengono lontano per non aggiungere nuovi problemi ai loro progetti, lasciando che la paura dell'ignoto li renda lontani dall'efficienza.

La ramificazione dovrebbe essere uno strumento semplice e potente che dovremmo usare per qualsiasi motivo abbastanza buono da ramificare.

Alcuni buoni motivi per le filiali:

  • lavorare su una funzionalità specifica in parallelo con altre persone (o mentre si lavora su altre funzionalità in alternativa se si è soli sul progetto);
  • con diverse versioni del marchio dell'applicazione;
  • avere versioni parallele della stessa applicazione - come tecniche simultanee sviluppate nello stesso tempo da una parte del team per vedere cosa funziona meglio;
  • avere risorse dell'applicazione modificate su un ramo specifico di artista / designer (ad esempio nei giochi) in cui l'applicazione è "stabile"; mentre altri rami e trunk vengono utilizzati per l'aggiunta e il debug delle funzionalità;
  • [aggiungi qui usi utili]

La ramificazione è banale. La fusione non lo è. Per questo motivo, raramente ramifichiamo qualsiasi cosa.

Usando SVN, ho scoperto che la ramificazione è relativamente indolore. Soprattutto se unisci periodicamente il tronco nel tuo ramo per evitare che si discosti troppo dalla sincronizzazione.

Usiamo svn. Ci vogliono solo circa 5 minuti per il codice della filiale. È banale rispetto alla quantità di dolore che ci salva dal disordine del tronco.

Lavorare in una base di codice di milioni di righe di codice con centinaia di diramazioni degli sviluppatori è un evento quotidiano. La vita del ramo varia a seconda della quantità di lavoro svolto.

Per una piccola correzione:

  • designer crea un sidebranch dallo stream principale
  • apporta modifiche
  • test
  • recensioni
  • unisce le modifiche accumulate dal flusso principale al sidebranch
  • scorre attraverso uno o più dei passaggi precedenti
  • torna allo stream principale

Per una funzione di squadra multipla:

  • il team crea una sidebranch di funzionalità al di fuori dello stream principale
  • il singolo membro del team opera sul sidebranch delle funzionalità come in "piccola correzione" si avvicina e si fonde con il sidebranch.
  • sidebranch prime unisce periodicamente le modifiche accumulate dal flusso principale a quello laterale. Piccole fusioni incrementali dal mainstream con il sidebranch sono molto più facili da gestire.
  • quando la funzione funziona, esegui l'unione finale dallo stream principale alla funzione sidebranch
  • unisci il sidebranch delle funzionalità allo stream principale

Per una versione software del cliente:

  • crea un ramo di rilascio
  • consegna le correzioni necessarie per rilasciare il ramo
  • le correzioni vengono propagate al / dal flusso principale in base alle esigenze

I flussi di rilascio dei clienti possono essere molto costosi da supportare. Richiede risorse di test: persone e attrezzature. Dopo un anno o due, le conoscenze degli sviluppatori su flussi specifici iniziano a diventare obsolete man mano che il flusso principale avanza.

Riesci a immaginare quanto deve costare Microsoft per supportare contemporaneamente XP, Vista e Windows 7? Pensa ai banchi di prova, all'amministrazione, alla documentazione, al servizio clienti e infine ai team di sviluppo.

Regola d'oro: Mai interrompi il flusso principale poiché puoi bloccare un gran numero di sviluppatori. $$$

Il problema delle ramificazioni è il motivo per cui utilizzo un sistema di controllo della versione distribuita (Git nel mio caso, ma ci sono anche Mercurial e Bazaar) in cui la creazione di una filiale è banale.

Uso sempre rami di breve durata per lo sviluppo. Questo mi permette di fare confusione nel mio repository, fare errori e scelte sbagliate, quindi rebase le modifiche al ramo principale in modo che nella cronologia vengano mantenute solo le modifiche pulite.

Uso tag s per contrassegnare il codice congelato, ed è facile in questi sistemi tornare indietro e ramificarli per correzioni di bug senza avere un carico di rami di lunga durata nella base di codice.

Uso Subversion e considero la ramificazione molto semplice e facile. Quindi, per rispondere alla domanda 1 .. Sì.

Il motivo della ramificazione può variare notevolmente. Mi dirigo se sento che dovrei. Abbastanza difficile stabilire regole e ragioni per tutte le possibilità.

Tuttavia, per quanto riguarda " Consenti a uno sviluppatore di evitare cambiamenti rischiosi. " commento. Sono totalmente d'accordo con quello. Creo un ramo ogni volta che voglio davvero giocare con il codice e vorrei essere l'unico sviluppatore a lavorarci su. Quando fai il ramo, puoi farlo ...

Sono stato su un progetto usando svn e TFS e la ramificazione da sola è una cosa davvero semplice.

Abbiamo usato la ramificazione per il rilascio candidato, nonché per caratteristiche di lunga durata o sperimentali e per isolare dalle interferenze di altri team.

L'unico momento doloroso nella ramificazione è la fusione, perché una filiale vecchia o intensamente sviluppata può differire molto dal tronco e potrebbe richiedere uno sforzo significativo per fondersi.

Detto questo, direi che la ramificazione è una pratica potente e utile che dovrebbe essere presa in considerazione durante lo sviluppo.

Se la fusione è troppo dolorosa, considera la migrazione a un VCS migliore. Sarà un dolore più grande, ma solo una volta.

Usiamo svn e abbiamo adottato una regola per ramificare le modifiche. Le modifiche minori vengono eseguite direttamente nel bagagliaio.

Distribuiamo anche filiali.

Branching e fusione hanno funzionato bene per noi. Concesso, ci sono volte in cui dobbiamo sederci e pensare a come le cose si incastrano, ma in genere svn fa un ottimo lavoro nel fondere tutto.

Uso svn, ci vuole meno di un minuto per diramare il codice. Usavo Clearcase, ci volle meno di un minuto per diramare il codice. Ho anche usato altri, minori, SCM e non supportavano i rami o erano troppo dolorosi da usare. Starteam sembra il secondo.

Quindi, se non riesci a migrare verso uno più utile (in realtà, ho sentito solo cose negative su Starteam), potresti dover provare un approccio diverso: la ramificazione manuale. Ciò comporta la verifica del codice, la copia in un'altra directory e quindi l'aggiunta come nuova directory. Quando è necessario unire, è necessario controllare entrambe le directory e utilizzare WinMerge per eseguire l'unione, controllando i risultati nella directory originale. Imbarazzante e potenzialmente difficile se si continua a utilizzare il ramo, ma funziona.

il trucco con Branching non è di trattarlo come un prodotto completamente nuovo. È un ramo: un dispositivo di durata relativamente breve utilizzato per apportare modifiche separatamente e in modo sicuro a un tronco di prodotto principale. Chiunque ritenga che la fusione sia difficile o sta riformattando così tanto i file di codice (ovvero stanno rinominando, copiando, creando nuovi, cancellando vecchi) che il ramo diventa una cosa completamente diversa, o stanno mantenendo il ramo così a lungo che sopportano le modifiche accumulate poca somiglianza con l'originale. Puoi mantenere un ramo per molto tempo, devi solo unire le modifiche regolarmente. Fai questo e ramificare / fondere diventa molto facile.

L'ho fatto solo un paio di volte, quindi non mi sento esattamente a mio agio.

L'ho fatto per condurre esperimenti di progettazione che si estendessero su alcuni check-in, quindi la ramificazione è un modo semplice per murare un giardino in cui giocare. Inoltre, mi ha permesso di armeggiare mentre altre persone lavoravano nel ramo principale , quindi non abbiamo perso molto tempo.

L'ho fatto anche quando ho apportato modifiche ad ampio raggio che avrebbero reso il tronco incompatibile. Nel mio progetto è diventato chiaro che avrei dovuto rimuovere la sicurezza del tipo in fase di compilazione per gran parte della base di codice (passare da generici a system.object). Sapevo che ci sarebbe voluto un po 'di tempo e che avrebbe richiesto cambiamenti in tutta la base di codice che avrebbero interferito con il lavoro degli altri. Avrebbe anche rotto la build fino al completamento. Così ho ramificato e messo a nudo i generici, lavorando fino a quando quel ramo non è stato compilato. L'ho quindi ricollocato nel bagagliaio.

Questo si è rivelato abbastanza bene. Ha impedito un sacco di passi in avanti, il che è stato fantastico. Spero che niente del genere possa mai più tornare. È una cosa rara che un design cambierà richiedendo questo tipo di modifiche ad ampio raggio che non comportano la cancellazione di molto codice ...

Le filiali devono essere gestite correttamente per rendere la fusione indolore. Nella mia esperienza (con Perforce) la regolare integrazione nella filiale dalla linea principale ha significato che l'integrazione nella linea principale è andata molto bene.

Ci sono state solo rare occasioni in cui la fusione non è riuscita. La costante integrazione dalla linea principale alla filiale potrebbe aver comportato fusioni, ma si trattava solo di piccole modifiche che gli strumenti automatici potevano gestire senza l'intervento umano. Ciò significa che l'utente non ha " vedi " questi stanno accadendo.

Pertanto, anche eventuali fusioni richieste nell'integrazione finale potrebbero essere gestite automaticamente.

Gli strumenti di unione a 3 vie di Perforces sono stati di grande aiuto quando erano effettivamente necessari.

  

Ti senti a tuo agio nel codice di ramificazione?

Dipende molto dallo strumento che sto usando. Con Starteam, la ramificazione non è in effetti banale (TBH, Starteam fa schifo alla ramificazione). Con Git, la ramificazione è un'attività regolare ed è molto semplice.

  

Si ramifica il codice per motivi diversi dal congelamento di un candidato al rilascio?

Bene, questo dipende davvero dal modello di controllo della versione, ma la risposta breve è sì. In realtà, suggerisco di leggere i seguenti articoli:

Mi piace molto il modello descritto nel primo articolo e può essere applicato con qualsiasi sistema di controllo della versione (non distribuito), incluso Starteam.

Potrei considerare il secondo approccio (in realtà, un mix di entrambe le strategie) con (e solo con) un Distributed Version Control Systems (DVCS) come Git, Mercurial ...

Usiamo StarTeam e ci ramifichiamo solo quando abbiamo una situazione che lo richiede (ovvero hotfix per la produzione durante il ciclo di rilascio o qualche progetto di vasta portata che si estende su più finestre di rilascio). Utilizziamo le etichette di visualizzazione per identificare le versioni e ciò rende semplice la creazione di filiali in seguito, se necessario. Tutte le build si basano su queste etichette di visualizzazione e non creiamo codice non etichettato.

Gli sviluppatori dovrebbero seguire un "codice - test - commit" modello e se hanno bisogno di una vista per qualche scopo di test o "rischioso" sviluppo lo creano e lo gestiscono. Gestisco il repository e creo filiali solo quando ne abbiamo bisogno. Quei tempi sono (ma non limitati a):

  • Aggiornamento rapido di produzione
  • Progetti con cicli di sviluppo lunghi o sovrapposti
  • Ampia riscrittura o sviluppo sperimentale

Lo strumento di unione in StarTeam non è il massimo, ma devo ancora imbattermi in un problema causato da esso. Chiunque stia facendo l'unione deve solo essere MOLTO sicuro di sapere cosa stanno facendo.

Creazione di un riferimento di sola lettura " la visualizzazione in Star Team e l'impostazione su una configurazione mobile consentirà di visualizzare automaticamente le modifiche nel trunk nel ramo. Imposta gli elementi da ramificare al cambio. Questo è utile per gli sforzi di sviluppo simultanei.

Creazione di un riferimento di sola lettura " visualizzare con una configurazione etichettata è quello che useresti per le hotfix per le versioni di produzione esistenti (supponendo che tu le abbia etichettate).

La ramificazione è banale, come molti hanno risposto, ma la fusione, come dici tu, non lo è.

Le chiavi reali sono il disaccoppiamento e i test unitari. Prova a disaccoppiare prima del tuo ramo e tieni d'occhio il principale per essere sicuro che il disaccoppiamento e l'interfaccia siano mantenuti. In questo modo, quando arriva il momento di fondersi, è come sostituire un pezzo lego: rimuovere il vecchio pezzo e il nuovo pezzo si adatta perfettamente al suo posto. I test unitari sono lì per garantire che nulla si sia rotto.

La ramificazione e la fusione dovrebbero essere abbastanza semplici.

  • Mi sento molto a mio agio nella ramificazione / fusione.
  • La ramificazione viene eseguita per diversi motivi, a seconda del modello del processo di sviluppo /

Esistono diversi modelli di filiali:

Eccone uno

  Trunk          
  .      
  .      
  .      
  ..         
  . ....     
  .   ...
  .      ..Release1
  .      
  .      
  ...        
  .  .... 
  .    ...Release2
  .      
  .      
  ..         
  . ...  
  .  .. 
  .    ...Release3
  .      
  .      

Ora ecco una cosa curiosa. Supponiamo che Release1 necessitasse di correzioni di bug. Ora è necessario ramificare Release1 per sviluppare 1.1. Va bene, perché ora puoi diramare R1, fare il tuo lavoro e quindi ricollegarti a R1 per formare R1.1. Notate come questo chiarisce le differenze tra le versioni?

Un altro modello di diramazione è quello di fare tutto lo sviluppo sul Trunk e ogni versione viene taggata, ma nessun ulteriore sviluppo viene fatto su quella particolare versione. Le succursali avvengono per lo sviluppo.

  Trunk                                           
  .                                                         
  .                                                         
  .                                                         
  .Release1           
  .                       
  .                       
  .                   
  .                   
  .Release2           
  .                   
  .......                 
  .      ......       
  .           ...DevVer1
  .          .    
  .          .            
  .        ...DevVer2
  .      ....         
  .  ....             
  ...                     
  .Release3           
      .

Potrebbero esserci uno o due altri modelli di diramazione principali, non riesco a ricordarli dalla cima della mia testa.

La linea di fondo è che il tuo VCS deve supportare la ramificazione e l'unione flessibili. I sistemi VCS per file presentano un forte dolore IMO (RCS, Clearcase, CVS). Si dice che SVN sia una seccatura anche qui, non so perché.

Mercurial fa un ottimo lavoro qui, come (credo) git.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top