I moduli 5 e 6 hanno coperto la metà del corso dedicata alla data platform: batch nel modulo 5, streaming nel modulo 6, due case study (Netflix e Uber) che hanno messo alla prova ogni primitivo lungo il percorso. Il modulo 7 apre un discorso diverso. I disegni architetturali dei moduli precedenti devono in qualche modo arrivare in produzione, e la strada da “abbiamo scritto il design” a “gira” passa per il codice, il version control, la code review, i test automatici, le deployment pipeline e il tooling operativo che tiene accese le luci. Di questo si occupa il modulo 7.
Il pezzo di apertura sceglie il tassello più universale di quella toolchain: git, e la domanda a cui ogni team di engineering risponde in qualche modo, ovvero come il team usa i branch. La risposta conta più di quello che sembra. La branching strategy plasma la cadenza delle review, la frequenza dei deploy, la frequenza dei merge conflict e la postura culturale del team verso il rilascio. Un team che usa gitflow rilascia in modo diverso da un team che usa trunk-based development, e la differenza non è solo di processo: è l’esperienza vissuta degli ingegneri.
Questa lezione copre le tre strategie che rappresentano quasi tutta la pratica professionale. Gitflow, GitHub flow, e trunk-based development. La lezione successiva fa zoom sul trunk-based development, perché è la strategia su cui converge la maggior parte dei team moderni, ed è quella che ripaga di più uno sguardo approfondito. La lezione 51 si occupa poi di CI per data pipeline, dove le pratiche astratte di software engineering incontrano la forma specifica del lavoro sui dati che il resto del corso sta costruendo.
Le tre strategie
Tre pattern dominano la scena. Si differenziano per la durata dei branch, la complessità dei merge, la cadenza di rilascio e il tooling che richiedono per funzionare. Non sono gli unici pattern. Sono quelli che la maggior parte dei team usa davvero, e quelli su cui è scritta la maggior parte del materiale pubblico.
Gitflow
Il post del 2010 di Vincent Driessen “A successful Git branching model” ha introdotto gitflow (https://nvie.com/posts/a-successful-git-branching-model/, consultato 2026-05-01). Il modello è gerarchico. Due branch a vita lunga ancorano il repo: main (talvolta chiamato master nelle convenzioni più vecchie) tiene il codice rilasciato in produzione, e develop tiene la linea di integrazione dove converge il lavoro in corso. Intorno a questi due, tre famiglie di branch a vita breve appaiono e scompaiono: feature branch da develop, release branch da develop quando si prepara una release, e hotfix branch da main quando un bug di produzione richiede una patch veloce.
Un ciclo di vita tipico. Uno sviluppatore crea feature/checkout-redesign da develop, lavora per una settimana, apre una pull request, viene revisionato, fa il merge di nuovo in develop. Diversi feature branch si accumulano su develop nell’arco di qualche settimana. Quando il team è pronto a rilasciare, un branch release/2.7.0 viene tagliato da develop. Il release branch accetta solo bug fix; il lavoro su nuove feature continua su develop. Quando il release branch è stabile, viene mergiato in main, taggato v2.7.0, e rimergiato in develop cosicche’ eventuali fix di release-time fluiscano in avanti. Un bug di produzione scoperto piu’ tardi genera un hotfix/2.7.1 da main, viene fixato, mergiato sia in main sia in develop, e il ciclo continua.
E’ molta cerimonia. La cerimonia esiste perche’ gitflow e’ stato progettato per prodotti con cicli di rilascio versionati e formali: software shrink-wrapped, app mobile che passano per la review dello store, software enterprise on-prem, librerie con semver. In quei contesti, separare “cosa c’e’ in sviluppo” da “cosa abbiamo rilasciato” e’ una vera preoccupazione architetturale, e i molteplici branch permettono al team di lavorare sulla prossima versione mentre supportano quella attuale.
GitHub flow
La documentazione di GitHub descrive un pattern molto piu’ semplice (https://docs.github.com/en/get-started/using-github/github-flow, consultato 2026-05-01). Un solo branch a vita lunga (main) tiene il codice production-ready. Ogni cambiamento, per quanto piccolo, avviene su un feature branch a vita breve da main. Il lavoro vive sul branch per ore o pochi giorni. Si apre una pull request, la CI esegue la test suite, un revisore approva, il branch viene mergiato in main. Il merge spesso fa scattare un deploy automatico.
La cadenza e’ continua. Non c’e’ “release branch” perche’ non c’e’ una release formale: ogni merge su main e’ una release, nel senso che e’ cio’ che sta girando in quel momento. Il pattern calza in modo naturale per SaaS e per la maggior parte delle web application, perche’ la superficie di deploy e’ un singolo sistema in esecuzione che si aggiorna in modo continuo. Calza anche per la maggior parte degli strumenti interni e per la maggior parte delle data pipeline, dove il target di deploy e’ un servizio che esegue l’ultima versione del codice.
GitHub flow e’ il pattern dominante nel mondo open-source e nella maggior parte delle organizzazioni di engineering moderne sotto qualche centinaio di ingegneri. E’ anche il piu’ facile da spiegare a qualcuno nuovo a git: “fai un branch, fai il tuo lavoro, apri una PR, mergiala, cancella il branch.”
Trunk-based development
Il terzo pattern fa un passo oltre il GitHub flow. Tutti committano direttamente su main. I branch esistono ancora per la code review, ma vivono per ore, non per giorni. Il lavoro non ancora pronto a essere esposto agli utenti si nasconde dietro feature flag: il codice e’ su main, deployato e testato, ma uno switch a runtime impedisce che giri finche’ il team non e’ pronto ad accenderlo.
Paul Hammant e altri hanno documentato il pattern su https://trunkbaseddevelopment.com (consultato 2026-05-01), basandosi sulle pratiche di organizzazioni di engineering su larga scala. Google, Facebook e Microsoft (per Azure DevOps e parte dello stack Office) gestiscono pubblicamente monorepo enormi con questo modello. Etsy e Spotify sono esempi di scala media che ne hanno scritto. Il filo comune e’ che a scala sufficiente le alternative smettono di funzionare: branch che vivono per una settimana entrano in conflitto con tutto cio’ che li circonda, e la risoluzione dei merge inizia a consumare una frazione reale del tempo di engineering.
Il trunk-based development richiede piu’ infrastruttura del GitHub flow. I feature flag diventano essenziali, non opzionali. La CI deve essere abbastanza veloce da validare ogni commit nel giro di minuti. La code review deve operare su cambiamenti piccoli, perche’ i cambiamenti atterrano direttamente sulla linea di integrazione. La lezione 50 copre tutto questo in profondita’.
Gli assi di confronto
Facendo un passo indietro, le tre strategie si separano nettamente lungo quattro assi.
Durata dei branch. Gitflow ha branch a vita lunga: develop e’ permanente, i feature branch spesso vivono settimane, i release branch giorni. GitHub flow ha branch a vita media: i feature branch vivono da ore a qualche giorno. Trunk-based ha branch a vita breve: ore, a volte minuti. Piu’ breve e’ la durata del branch, meno divergenza si accumula tra cio’ su cui stai lavorando e l’aspetto di main.
Complessita’ del merge. Discende direttamente dalla durata del branch. Branch a vita lunga entrano in conflitto con tutto cio’ che li circonda, quindi mergiarli e’ un’operazione vera. Branch a vita breve divergono appena da main, percio’ i merge sono di solito fast-forward o three-way merge banali. I team che odiano mergiare sono di solito team con branch che vivono troppo a lungo.
Cadenza di rilascio. Gitflow assume rilasci pianificati: il team prepara un release branch, lo stabilizza, lo rilascia, ripete. GitHub flow assume rilasci continui: ogni merge su main e’ un rilascio. Trunk-based assume continuous deployment: ogni merge puo’ essere deployato automaticamente, spesso lo e’, e la domanda “cosa c’e’ in questa release” diventa “cosa c’era su main al momento del deploy”.
Tooling richiesto. Gitflow richiede il minimo tooling: il modello funziona con git nudo e un sistema di CI. GitHub flow richiede CI su ogni PR e idealmente deploy automatici. Trunk-based richiede tutto questo piu’ un’infrastruttura di feature flag, piu’ una pipeline di CI abbastanza veloce e affidabile da rendere non terrificante il commit diretto su main. Il costo di tooling del trunk-based e’ reale, ed e’ il motivo per cui i team piccoli spesso partono con GitHub flow e si spostano sul trunk-based quando la scala lo richiede.
flowchart LR
subgraph main ["main branch"]
direction LR
m1["init"] --> m2["small fix"] --> m3["merge login<br/>deploy"] --> m4["merge api<br/>deploy"] --> m5["merge dashboard<br/>deploy"]
end
subgraph login ["feature/login"]
direction LR
l1["login UI"] --> l2["login tests"]
end
subgraph api ["feature/api"]
direction LR
a1["api endpoint"]
end
subgraph dash ["feature/dashboard"]
direction LR
d1["dashboard"] --> d2["dashboard tests"]
end
m2 -.branch.-> l1
l2 -.merge.-> m3
m2 -.branch.-> a1
a1 -.merge.-> m4
m3 -.branch.-> d1
d2 -.merge.-> m5
classDef mainNode fill:#0d9488,stroke:#0d9488,color:#ffffff
classDef branchNode fill:#1f2933,stroke:#52606d,color:#e8edf1
classDef boundary fill:transparent,stroke:#0d9488,stroke-dasharray: 5 5
class m1,m2,m3,m4,m5 mainNode
class l1,l2,a1,d1,d2 branchNode
class main,login,api,dash boundary
Diagramma da creare: una versione rifinita del gitGraph del GitHub flow qui sopra.
maine’ la spina dorsale centrale, tre feature branch a vita breve si staccano e rientrano nell’arco di qualche giorno, e dei marcatori “deploy” siedono sui commit di merge. Il punto visivo e’ chemaine’ sempre rilasciabile, i branch sono brevi e i merge avvengono in modo continuo.
Quando ciascuna strategia calza
Le strategie sono strumenti, non religioni. Il fit dipende da cosa il team sta rilasciando.
Gitflow calza per prodotti con rilasci versionati. App mobile dove la review dell’App Store e’ il deploy gate. Librerie con semver dove gli utenti pinnano versioni specifiche. Software enterprise on-prem rilasciato trimestralmente. Firmware embedded. La caratteristica comune e’ che esiste una differenza significativa tra “cosa abbiamo rilasciato” e “cosa stiamo facendo”, e il branching model rende esplicita quella differenza. La cerimonia di gitflow e’ appropriata quando il processo di rilascio sottostante e’ a sua volta cerimonioso.
GitHub flow calza per la maggior parte dei SaaS, la maggior parte degli strumenti interni e la maggior parte delle data pipeline. Il target di deploy e’ un singolo sistema in esecuzione. I rilasci sono continui. Il team e’ abbastanza piccolo perche’ i branch a vita lunga siano superflui. L’infrastruttura di feature flag puo’ esistere ma non e’ un prerequisito stringente. E’ qui che avviene il grosso dell’engineering professionale, ed e’ il default sicuro per un team che non ha una ragione specifica per scegliere altro.
Trunk-based calza per team molto grandi o per team impegnati nel continuous deployment. Due popolazioni distinte finiscono qui. La prima e’ quella dei team abbastanza grandi da rendere doloroso il branching tout court: centinaia di ingegneri che committano su un monorepo non possono permettersi branch lunghi una settimana perche’ il costo del merge domina. La seconda e’ quella dei team con una forte cultura dei feature flag che vogliono la disciplina di “tutto su main, gated da una flag” perche’ elimina un’intera classe di bug di integrazione. Entrambe le popolazioni traggono benefici reali dal pattern; entrambe pagano la tassa di tooling che il pattern richiede.
Il confine tra GitHub flow e trunk-based e’ sfocato in pratica. Un team piccolo che usa GitHub flow con branch da un giorno e una CI loop veloce sta gia’ quasi facendo trunk-based. La differenza culturale sta nel fatto che il team pensi a main come “il branch di integrazione su cui mergiamo” (GitHub flow) o come “il posto dove lavoriamo, con i branch come formalita’ di review” (trunk-based). La differenza meccanica sta nel fatto che i feature flag siano una parte di routine del workflow o un caso speciale.
La piega del data engineering
Le data pipeline complicano il quadro in un modo specifico: le schema migration e i sistemi stateful non rotolano in avanti con la pulizia con cui lo fa il codice stateless.
Un servizio web puo’ essere deployato due volte al giorno, dieci volte al giorno, su ogni commit. Una pipeline che scrive su una tabella di warehouse non puo’. Se il cambiamento alla pipeline include una schema migration (una nuova colonna, una colonna rinominata, un tipo cambiato), la migration gira una volta sola, contro un warehouse reale, e fare rollback significa annullare la migration, che a volte e’ impossibile. La branching strategy interagisce con questo in due modi.
Primo, i branch a vita lunga sono piu’ rischiosi per il codice di pipeline che per quello di servizio. Se il branch feature/customer-360 vive per tre settimane mentre il team lavora a un nuovo dimension model, e nella seconda settimana main rilascia un cambiamento di schema diverso, mergiare il branch diventa un esercizio forense: quale schema e’ corretto, quale migration gira per prima, che aspetto ha il warehouse a ciascun punto. Piu’ breve il branch, piu’ piccolo il problema.
Secondo, i feature flag sono scomodi per le pipeline batch. Una flag che fa da gate a un percorso di codice in un request handler e’ economica; la flag viene controllata, il percorso viene preso, la richiesta torna. Una flag che fa da gate a una trasformazione in un job batch notturno e’ la stessa idea, ma le conseguenze di un valore di flag sbagliato sono persistenti: i dati sono stati scritti, in una forma o nell’altra, e non puoi descriverli senza un backfill. Il trunk-based development per le data pipeline richiede un investimento in job idempotenti (lezione 38) e in macchinari di backfill affidabili (lezione 39), cosicche’ gli output “sbagliati” possano essere rigenerati.
La raccomandazione pratica per la maggior parte dei data team e’ GitHub flow con branch brevi e disciplinati, CI che esegue la pipeline su dati di sample (lezione 51), e migration gated dietro deploy step espliciti che il team approva separatamente dai merge di codice. Il trunk-based per le data pipeline e’ raggiungibile, e le lezioni successive del modulo 7 ne descrivono i pattern, ma i prerequisiti sono reali.
Dove ci lascia tutto questo
La branching strategy e’ la scelta di superficie. Sotto, la domanda piu’ profonda e’ come il team si rapporta alla linea di integrazione: main e’ una destinazione a cui arrivi dopo una preparazione, o uno spazio di lavoro su cui vivi in modo continuo? Gitflow tratta main come la destinazione. GitHub flow tratta main sia come spazio di lavoro sia come linea di deploy. Trunk-based tratta main come spazio di lavoro e scommette sui feature flag per tenere sicura la linea di deploy.
La lezione 50 smonta il pattern trunk-based nel dettaglio: perche’ le piu’ grandi organizzazioni di engineering ci sono convergenti, quali sono i prerequisiti, come funzionano i feature flag, e il cambiamento culturale che il pattern richiede agli sviluppatori. La lezione 51 si occupa poi di CI per data pipeline, che e’ la disciplina di testing che rende sicura una qualunque di queste branching strategy in un contesto di data engineering.
Citazioni e letture di approfondimento
- Vincent Driessen, “A successful Git branching model”, 2010,
https://nvie.com/posts/a-successful-git-branching-model/(consultato 2026-05-01). La proposta originale di gitflow, con i diagrammi diventati il riferimento standard. - GitHub Docs, “GitHub flow”,
https://docs.github.com/en/get-started/using-github/github-flow(consultato 2026-05-01). La descrizione canonica del GitHub flow come praticato sulla piattaforma. - Paul Hammant e contributori, “Trunk-Based Development”,
https://trunkbaseddevelopment.com(consultato 2026-05-01). Il sito di riferimento per il trunk-based development, inclusi i case study di organizzazioni di engineering su larga scala. - Atlassian, “Comparing workflows”,
https://www.atlassian.com/git/tutorials/comparing-workflows(consultato 2026-05-01). Un confronto vendor-neutral fianco a fianco dei principali pattern, utile come riferimento didattico.