Creazione di rami strategici

Azure DevOps Services | Azure DevOps Server 2020 | Azure DevOps Server 2019 | TFS 2018

Il codice sorgente è una risorsa importante nel lavoro di sviluppo. Una gestione e un'elaborazione efficaci dei file di origine, tuttavia, possono rappresentare una sfida impegnativa quando più sviluppatori si occupano simultaneamente degli aggiornamenti dei file. È possibile usare un sistema di controllo della versione per archiviare il codice sorgente in repository condivisi, isolare attività di sviluppo parallele, integrare modifiche al codice e recuperare versioni precedenti dei file. Un elemento chiave nel controllo della versione è la creazione di rami che consente attività di sviluppo simultanee. La creazione di rami eseguita in modo strategico consente di mantenere l'ordine e la coerenza di più versioni del software.

Team Foundation offre un sistema di controllo delle versioni flessibile e affidabile. È possibile usare il controllo della versione di Team Foundation per gestire più revisioni durante lo sviluppo di codice sorgente, documenti, elementi di lavoro e altre informazioni critiche eseguite dal team.

In che modo il team gestisce il codice quando si introducono simultaneamente più modifiche in diversi rilasci del progetto?

Quando si usa un sistema di controllo della versione, è necessario valutare come configurare una struttura di rami. È possibile creare un ramo eseguendo il mirroring del file del codice sorgente. È quindi possibile modificare il ramo senza influire sull'origine. Come illustrato dalla struttura di rami nella figura seguente, ad esempio, il ramo MAIN contiene una funzionalità completata che ha superato i test di integrazione, mentre il ramo DEVELOPMENT contiene il codice in fase di creazione. Quando una nuova funzionalità inclusa nel ramo DEVELOPMENT viene completata e supera i test di integrazione, è possibile alzare di livello il codice dal ramo DEVELOPMENT al ramo MAIN. Questo processo è denominato integrazione all'indietro. Al contrario, il processo di unione del codice dal ramo MAIN al ramo DEVELOPMENT è denominato integrazione in avanti.

Main Branch
Per altre informazioni su come creare e unire i rami del codice, vedere la pagina seguente nel sito Web CodePlex: Team Foundation Server Branching Guide 2.0.

Le operazioni di creazione rami e unione comportano i principi seguenti:

  1. Per ogni ramo devono essere definiti i criteri su come integrare il codice nel ramo. Nella struttura di rami della figura precedente, ad esempio, è possibile assegnare un membro del team come proprietario e responsabile della gestione del ramo MAIN. Questo membro è responsabile dell'esecuzione dell'operazione iniziale di creazione rami, dell'integrazione all'indietro delle modifiche dal ramo DEVELOPMENT al ramo MAIN e dell'integrazione in avanti delle modifiche dal ramo MAIN al ramo DEVELOPMENT. L'integrazione in avanti è importante quando il ramo MAIN integra anche modifiche da altri rami.

  2. Il ramo MAIN deve contenere codice che abbia superato i test di integrazione, in modo che sia sempre pronto per il rilascio di una versione.

  3. Il ramo DEVELOPMENT (o di lavoro) evolve continuamente, in quanto i membri del team archiviano periodicamente le modifiche.

  4. Le etichette sono snapshot dei file presenti in un ramo in un momento specifico.

    Per altre informazioni, vedere Usare le etichette per acquisire uno snapshot dei file.

Team Foundation Build consente di scegliere tra diversi tipi di compilazioni per i rami: manuale, continuo, gated, rolld e pianificato. È consigliabile che il ramo MAIN abbia un tipo di compilazione con archiviazione gestita. Ciò significa che il ramo DEVELOPMENT deve soddisfare tutti i requisiti per il ramo MAIN prima di poter eseguire un'integrazione all'indietro. Il ramo DEVELOPMENT deve eseguire un tipo di compilazione continua, in quanto il team deve essere informato il prima possibile se una nuova archiviazione influisce sul ramo DEVELOPMENT.

Con quale frequenza il team deve eseguire le integrazioni all'indietro e in avanti?

Come illustrato nella figura seguente, l'integrazione all'indietro e l'integrazione in avanti devono essere eseguite almeno quando si completa una storia utente. Benché ogni team possa definire in modo diverso la completezza, il completamento di una storia utente indica in genere che sono stati completati sia la funzionalità che gli unit test corrispondenti. È possibile eseguire l'integrazione all'indietro nel ramo MAIN solo dopo che gli unit test hanno verificato la stabilità del ramo DEVELOPMENT.

Branch across two sprints
Se sono presenti più rami di lavoro (DEVELOPMENT), l'integrazione in avanti in tutti i rami di lavoro deve essere eseguita non appena un ramo viene integrato nel ramo MAIN. Poiché il ramo MAIN viene mantenuto stabile, l'integrazione in avanti è un'operazione sicura. Possono verificarsi conflitti o errori nei rami di lavoro perché non è possibile garantire la stabilità dei rami di lavoro.

È importante risolvere tutti i conflitti il prima possibile. L'uso di un'archiviazione gestita per il ramo MAIN consente di semplificare significativamente l'integrazione all'indietro, in quanto i controlli di qualità consentono di evitare conflitti o errori nel ramo MAIN. Per altre informazioni, vedere Accedere a una cartella controllata da un processo di compilazione del check-in gated.

In che modo il team gestisce le origini che implementano storie utente diverse?

Come illustrato nella figura seguente, è possibile archiviare periodicamente le modifiche in un ramo di lavoro per completare una storia utente. È possibile implementare contemporaneamente più storie utente nello stesso ramo. È tuttavia possibile eseguire l'integrazione all'indietro nel ramo MAIN solo dopo aver completato tutto il lavoro in corso. È consigliabile raggruppare le storie utente per dimensioni simili, in quanto è necessario evitare che una storia utente di grandi dimensioni blocchi l'integrazione di molte storie utente più piccole. È possibile suddividere i due set di storie utente in due rami.

Check-in Completes User story

Quando il team deve aggiungere un ramo?

È necessario creare i rami nelle situazioni seguenti:

  • Quando è necessario rilasciare il codice in un diverso ciclo o una diversa pianificazione rispetto ai rami esistenti.

  • Quando il codice richiede criteri diversi per i rami. Se si crea un nuovo ramo con nuovi criteri, è possibile aggiungere valore strategico al progetto.

  • Quando la funzionalità viene rilasciata a un cliente e il team prevede di apportare modifiche che non influiranno sul ciclo di rilascio pianificato.

Non è consigliabile creare un ramo per ogni storia utente, perché ciò comporta costi di integrazione elevati. Anche se TFVC semplifica il ramo, il sovraccarico della gestione dei rami può diventare significativo se si dispone di molti rami.

In che modo il team gestisce i rilasci dal punto di vista del controllo della versione?

Il team deve essere in grado di rilasciare il codice alla fine di qualsiasi sprint. Usando Team Foundation Server , è possibile etichettare un ramo per acquisire uno snapshot del codice in un momento specifico. Come illustrato nella figura seguente, è possibile applicare un'etichetta al ramo MAIN per un rilascio. Ciò consente di tornare allo stato del ramo di quel momento specifico.

Label a branch to take a snapshot of the code
Poiché può essere necessario implementare aggiornamenti per i rilasci, la creazione di un ramo per un rilascio consentirà al team di continuare a lavorare in modo indipendente sullo sprint successivo senza creare conflitti con i rilasci futuri. La figura seguente illustra un ramo contenente il codice per un aggiornamento e su cui viene eseguita un'integrazione all'indietro nel ramo MAIN dopo un rilascio alla fine del secondo sprint.

Reverse integrate a branch that contains update
Quando si crea un ramo per una rilascio, è consigliabile crearlo dal ramo MAIN, che è più stabile. La creazione di un ramo per un rilascio da un ramo di lavoro può provocare difficoltà di integrazione, in quanto la stabilità dei rami di lavoro non è garantita.