Git è un distributed version control system oramai largamente utilizzato anche grazie al famosissimo portale Github. Dopo aver utilizzato per un po’ di tempo Git ci si accorge che è necessario stabilire dei propri processi standardizzati, tali da rendere efficiente l’intero sviluppo: tale aspetto lo ha compreso per primo Vincent Driessen che nel 2009 ha ideato un nuovo development model e lo ha reso pubblico circa un anno dopo.

Chi conosce già il versioning con Git, potrebbe cimentarsi ad utilizzare “la tecnica” GitFlow, rappresentante non tanto un reale cambiamento rispetto a Git, ma piuttosto un insieme di strategie sul come utilizzare Git e i suoi branch in modo proficuo e gestire un flusso di lavoro pulito (versioni, bugfix e release in ambiente condiviso e, perché no, anche quando si lavora da soli su piccoli progetti).

GitFlow è l’ideale per i progetti che hanno un ciclo di vita ben definito, con release continue e hotfix tempestivi. È basato sull’idea che ogni ramo (branch) ha uno scopo ben preciso ed altrettanto precise sono le regole che deve seguire. Ad esempio, GitFlow usa branch specifici per preparare, mantenere e pubblicare ciascuna release, mentre è usato un altro modello per gestire le feature che svilupperemo o per gli hotfix da rilasciare al volo.

Prima di procedere nel mondo Git Flow, è bene precisare la possibilità di utilizzare la tecnica in due modi: il primo utilizzando comuni comandi git, il secondo impiegando lo strumento git-flow che è un wrapper che ci permette di accorpare diversi comandi “semplici” git. Per ciascuna funzione vedremo come eseguirla sia con questi ultimi sia con la forma abbreviata che ci offre git-flow.

I VANTAGGI DI GIT FLOW

Chi usa tutta la potenza di Git fa largo uso di Git Flow perché esso permette di:

- Sviluppare in parallelo: i nuovi sviluppi sono organizzati in feature branches e vengono merged (cioè accorpati) nel codice principale solo quando il team reputa che sia pronto per il rilascio. Ciò permette di cambiare task senza problemi.

- Aumentare la collaborazione: le feature branches permettono a più sviluppatori di lavorare su una singola feature, in quanto essa agisce come una sandbox e tutti gli sviluppi vengono effettuati affinché la stessa venga portata in produzione. Ciò permette anche di verificare il lavoro svolto dai singoli sviluppatori su una feature.

- Avere una Release Staging Area: i nuovi sviluppi vengono merged in una develop branch, che di fatto rappresenta una staging area per tutti gli sviluppi che non sono stati ancora rilasciati. Questo vuol dire che quando avviene un rilascio, quest’ultimo ha all’interno tutti gli sviluppi nella develop branch.

COME FUNZIONA GIT FLOW: BRANCH DEVELOP E MASTER

Chiunque conosca Git sa che il branch master è il core di ogni progetto, perché rispecchia la versione pubblica attualmente in produzione, la versione cioè accessibile agli utenti. A titolo di esempio, se il nostro progetto fosse lo sviluppo di una App, essa rispecchierebbe la versione attualmente scaricabile dal Play Store o App Store.

L’approccio GitFlow utilizza due rami principali per gestire il controllo di versione (versioning) del progetto: il primo, si tratta del master che conserva, come detto, tutte le release; il secondo è il ramo develop, che è fondamentale per lo sviluppo delle prossime versioni e serve come base per le future integrazioni. È inoltre conveniente taggare tutti i commit (o merge) verso il master con un numero di versione progressiva.

Tutta la (futura) vita del nostro progetto ruoterà quindi attorno ai due rami master e develop ed essi saranno il punto di partenza e di arrivo degli altri rami e saranno l’ossatura vera e propria del repository.

 

NUOVE FUNZIONALITA' (FEATURE BRANCH)

Dopo aver sistemato i nostri rami fondamentali, master e develop, passiamo alla gestione delle nuove funzionalità (feature) che implementiamo sul progetto.

Ogni nuova feature, quindi, dovrebbe avere il proprio branch, che deve essere presente anche su origin in modo da permettere agli altri sviluppatori di collaborare. I rami delle nuove funzionalità devono essere creati a partire da quello develop e, quando abbiamo completato lo sviluppo della funzionalità, deve essere unito (merge) di nuovo in develop. Non deve, MAI, essere unito direttamente a master.

Come creare un feature branch?

Vediamo come farlo con i comuni comandi git. Partiremo, come detto, dall’ultima versione del ramo develop:

 

git checkout develop

git checkout -b feature/nuova_funzione

 

Lo stesso esempio utilizzando git-flow:

git flow feature start nuova funzione

 

È prassi che i nomi dei rami abbiamo la forma tipo/nome_ramo. Nel caso sopracitato il nome del nuovo branch è feature/nuova_funzione.

Come completare un feature branch?

Dopo aver completato lo sviluppo della nuova funzione, è ora di aggiornare il ramo develop con le ultime modifiche.

Con i semplici comandi git, ci spostiamo sui develop ed effettuiamo l’unione (merge) del ramo:

 

git checkout develop

git merge feature/nuova_funzione

 

Utilizzando git-flow la forma è più breve:

git flow feature finish feature/nuova_funzione

 

Fine: a questo punto, le nostre novità scritte nel ramo feature/nuova_funzione  non sono pronte per essere rilasciate, essendo state unite nel ramo develop e non in quello master che, come dicevamo, corrisponde alla versione pubblica del nostro progetto, cioè quella attualmente utilizzata dagli utenti.

FINALIZZARE UNA RELEASE

Una volta che il ramo develop ha accumulato, tramite unioni (merge), abbastanza feature, siamo pronti per approcciare una nuova release del progetto. Per farlo, creiamo un ramo (branch) a partire da develop. Su questo nuovo ramo, che per prassi avrà un nome del tipo release/1.2, non dovremmo scrivere nuove integrazioni, ma limitarci a quei piccoli compiti che porta dietro ogni release, come fixare gli ultimi bug, aggiungere documentazione, pulire o aggiungere commenti, etc.

Quando il ramo è pronto, dovremmo unirlo nel ramo master e poi nuovamente nel ramo develop.

Utilizzare questo approccio permette agli sviluppatori di lavorare e finalizzare una release mentre è possibile ancora lavorare parallelamente su altre funzioni (cioè su altri rami feature/*) che non sono state ancora rilasciate. Inoltre, utilizzando una struttura dei nomi formale e condivisa, si può capire subito, a colpo d’occhio, lo stato attuale del progetto.

Non ci rimane poi che aggiungere un tag al merge (ovvero al commit risultante dall’unione) tra master e release/1.2 con appunto il numero di versione 1.2.

Vediamo come creare un branch di release con i comuni comandi git:

 

git checkout develop

git checkout -b release/1.2

 

Se volessimo farlo con git-flow:

git flow release start 1.2

Switched to a new branch 'release/1.2'

 

Come dicevamo, a questo punto ci troviamo sul nuovo ramo e possiamo andare ad eseguire bugfix e altre operazioni per prepararci al rilascio di questa versione. Una volta pronti, faremo il merge di questo ramo in master, poi in develop e poi potremmo semplicemente cancellarlo. Il motivo dell’unione in develop è semplice: ipotizzando di aver fixato qualche bug critico, l’avremmo fixato anche nelle altre (future) versioni.

 

 

Per finalizzarlo, ovvero rilasciare una nuova versione del nostro progetto, lo uniremo in master, poi in develop:

 

Con i comandi git:

git checkout develop

git merge release/1.2

git checkout master

git merge release/1.2

git tag 1.2 git branch -D release/1.2

 

Con l’estensione git-flow tutto si riassume in un unico comando:

git flow release finish '1.2'

 

CREARE UN HOTFIX

I rami (branch) di hotfix vengono usati per aggiustare bug che affliggono la release attualmente in produzione. Sono fondamentali perché ci permetteranno di gestire bug che al momento i nostri utenti stanno “subendo” oppure di tappare falle di sicurezza zero-day.

Per questo motivo, i rami hotfix hanno un flusso più rapido rispetto ai rami visti in precedenza. Considerato che fixano bug già distribuiti, un ramo hotfix/nomebug verrà creato a partire direttamente da master e, una volta corretto il problema, dovrà essere unito (merge) sia in master che develop (oppure nella release che attualmente si sta preparando).

Un approccio di questo tipo ci permetterà quindi di fare bug fix senza interrompere i lavori al progetto su altri rami rendendo però questo nuovo fix disponibile anche per le future release.

Vediamo come creare un ramo hotfix con i comuni comandi git:

 

git checkout master

git checkout -b hotfix/nomebug

 

Utilizzando l’estensione git-flow, invece:

git flow hotfix start nomebug

 

Quando avremo terminato la scrittura del nostro fix, facciamo il merge di questo ramo in develop e in master. Poi, possiamo semplicemente cancellarlo. Usando i comandi git:

 

git checkout master

git merge hotfix/nomebug

git tag 1.2.1

git checkout develop

git merge hotfix/nomebug

git branch -D hotfix/nomebug

 

Con git-flow basterà un solo comando:

git flow hotfix finish nomebug

 

Come già riportato in precedenza, ogni commit o merge nel ramo master genererà una nuova release number, che nel nostro esempio sarà 1.2.1.

 

La semplificazione della gestione di branches, release, develop e staging area, che crea vantaggi relativi soprattutto all’incremento della collaborazione e allo sviluppo in parallelo, porta Wonderlab ad utilizzare Git Flow nei suoi progetti IT, con importanti ricadute positive nello sviluppo di codice.

Articoli Recenti