Su AZ-400 la strategia di branching è una decisione architetturale: determina lead time, rischio di rilascio e capacità di dimostrare la tracciabilità a un auditor. La domanda d’esame non è “come creo un branch”, ma “dato questo profilo di rilascio, questo team e questi vincoli di compliance, quale topologia e quale set di policy la rendono esecutiva”. Diamo per acquisiti i meccanismi Git di base e concentriamoci su criteri di scelta e trade-off.

Trunk-based, feature branch, release branch: i criteri di scelta

Le tre topologie non sono alternative pure. La guidance Microsoft per Azure Repos parte da un modello feature branch su main: branch brevi (o topic branch) per ogni feature e bugfix, merge in main solo tramite pull request, main sempre buildabile e testato. Il trunk-based development è la versione estrema dello stesso modello.

Frequenza di rilascio. Più deployi, più il branch deve essere corto: con deployment su ogni merge, un branch di lunga vita è un debito che paghi in conflitti e regressioni non integrate. Il vincolo però non è tecnico ma di feature flag, indicati dalla guidance come lo strumento per gestire il lavoro a lunga durata senza branch a lunga durata. Senza flag maturi il trunk-based puro porta funzionalità incomplete in produzione, e il feature branch resta la scelta difendibile.

Dimensione del team. Un team piccolo converge su trunk con revisione leggera. In un team grande il problema non è la topologia ma la serializzazione dell’integrazione: GitHub risponde con la merge queue, che accoda le PR e le valida contro lo stato che avranno dopo il merge, intercettando i conflitti semantici che il check della singola PR non vede. Si configura a livello di repository e non è disponibile nei ruleset di organizzazione: non la standardizzi centralmente.

Compliance e supporto a più versioni. Il release branch entra in gioco quando devi supportare più versioni rilasciate insieme, o quando la normativa impone un artefatto stabile e ricostruibile. È un branch di lunga vita che non viene reintegrato in main via pull request: ogni release branch attivo è una versione in più da mantenere, e va bloccato a fine supporto. La decisione cruciale è la direzione delle correzioni, con due approcci opposti:

  • Fix nel release branch, poi porting verso main tramite cherry-pick su un feature branch e seconda PR. Il cherry-pick, non il merge, è la scelta corretta: fondere il release branch in main trascinerebbe modifiche specifiche del rilascio.
  • Fix sempre in mainline, poi porting verso il release branch: è la strategia Release Flow adottata dal team Azure DevOps. Costa un ciclo in più sull’hotfix urgente, ma elimina strutturalmente la classe di difetti “corretto in produzione, regredito alla release successiva”.

Il primo approccio ottimizza il tempo di risposta all’incidente, il secondo la correttezza. In uno scenario che parla di regressioni ricorrenti fra release, la risposta è mainline-first.

Rendere la strategia esecutiva: branch policy in Azure Repos

Una strategia non scritta nelle policy è una convenzione, e le convenzioni non superano un audit. In Azure Repos il gate si costruisce con le branch policy sul branch protetto, tra cui numero minimo di reviewer, check for linked work items, comment resolution, build validation, status check esterni, automatically include reviewers e limit merge types. Le leve rilevanti in fase di design:

  • Reviewer minimi. La guidance Microsoft indica due reviewer come numero ottimale sulla base di ricerca, e raccomanda di distribuire la responsabilità di revisione invece di concentrarla sulle stesse persone. Nel dettaglio contano due opzioni: reset dei voti di approvazione quando il branch sorgente riceve nuovi push (chi approva deve aver visto il codice finale) e allow requestors to approve their own changes, da disattivare dove serve separation of duties.
  • Automatically include reviewers con path filter. È il meccanismo con cui imponi che le modifiche a un’area sensibile passino da un gruppo specifico, l’equivalente funzionale di CODEOWNERS.
  • Check for linked work items. Poco vistosa ma centrale per la tracciabilità: lega la modifica all’elemento di backlog che la giustifica.
  • Bypass. Azure Repos distingue due permessi separati: bypass policies when completing pull requests e bypass policies when pushing, assegnabili a progetto, repo o singolo branch. Concedili al minor scope possibile. Nota il comportamento: per chi ha il bypass le policy vengono comunque valutate, ma lo stato riportato è solo consultivo e non blocca il completamento.

Il modello GitHub: branch protection rule e ruleset

Su GitHub la distinzione da padroneggiare è fra la vecchia branch protection rule e il ruleset. Tre differenze sostanziali:

  • Più ruleset possono applicarsi contemporaneamente allo stesso branch e le regole si aggregano, con la più restrittiva che prevale in caso di conflitto. È il motivo per cui in uno scenario “policy di piattaforma centrale più regole specifiche del team, senza che l’una escluda l’altra” la risposta è ruleset.
  • Visibilità: chiunque abbia accesso in lettura vede i ruleset attivi, senza permessi di amministrazione.
  • Enforcement su tre stati: Active, Disabled e soprattutto Evaluate, che non applica le regole ma registra su Rule Insights quali azioni le avrebbero violate. È la risposta per “introdurre una policy stringente su un repository attivo senza bloccare i team il primo giorno”.

Il catalogo di regole copre, tra le altre, require a pull request before merging (con approvazioni minime, dismiss delle approvazioni obsolete, revisione dei code owner e metodi di merge consentiti), require status checks to pass, require linear history, require signed commits, require deployments to succeed, block force pushes e restrizioni su creazione, aggiornamento e cancellazione dei branch. I ruleset a livello di organizzazione richiedono GitHub Team o GitHub Enterprise e non sono disponibili sul piano Free: è il vincolo di piano da ricordare quando serve una policy uniforme su decine di repository.

Il bypass si concede a utenti, ruoli, team e GitHub App in due modalità: Always allow, oppure for pull requests only, che obbliga comunque a passare da una pull request lasciando traccia nel log di audit. La seconda è quasi sempre la risposta corretta in contesto regolato: non elimina il controllo, ne conserva l’evidenza.

Strategie di merge: cosa scegli davvero

Azure Repos limita i tipi di merge fra quattro opzioni: basic merge (no fast-forward), che crea un merge commit con due parent e conserva la storia non lineare; squash merge, che condensa il branch in un solo commit sul target; rebase and fast-forward, che riproduce i commit senza merge commit; rebase with merge commit, che li riproduce e aggiunge comunque un merge commit, per una storia semi-lineare. GitHub espone tre metodi: merge commit, squash e rebase.

I trade-off da saper argomentare:

  • Lo squash dà una storia leggibile, un commit per unità di lavoro. Il prezzo, esplicitato dalla documentazione GitHub, è la perdita dell’informazione su quando e da chi le singole modifiche sono state fatte, oltre a conflitti se si continua a lavorare sul branch dopo lo squash.
  • Il rebase su GitHub ha un vincolo decisivo: i commit vengono aggiunti al branch base senza verifica della firma, perché GitHub crea un commit modificato e non dispone della chiave privata per firmarlo. Se il requisito è require signed commits, rebase lato server e firma sono in tensione, e la documentazione indica il rebase locale come soluzione.
  • Il merge commit conserva tutto, incluso il rumore. La regola require linear history lo esclude per costruzione: se lo scenario impone storia lineare, le opzioni con merge commit sono automaticamente errate.

Come cade all’esame

Il pattern ricorrente è uno scenario narrativo con team, cadenza di rilascio e un vincolo normativo, che chiede la combinazione minima di impostazioni. Trappole tipiche:

  • “Ogni modifica in produzione deve essere riconducibile a una richiesta approvata” → policy check for linked work items in Azure Repos, non processi manuali.
  • “Le modifiche a una directory sensibile richiedono l’approvazione di un gruppo specifico”automatically include reviewers con path filter su Azure Repos, code owner review su GitHub; non affidarsi alla convenzione.
  • “Un approvatore ha già approvato, poi lo sviluppatore ha spinto altro codice”reset dei voti al push sul sorgente in Azure Repos, dismiss stale approvals su GitHub.
  • “Applicare una policy severa senza bloccare i team durante la transizione” → ruleset in Evaluate, non ruleset Active con bypass diffusi.
  • “Serve storia lineare e commit firmati” → attenzione al rebase lato server, che non preserva la verifica della firma.
  • “Le correzioni di produzione regrediscono alla release successiva”mainline-first con porting verso il release branch (Release Flow), oppure cherry-pick verso main; mai merge del release branch in main.
  • “Le PR passano i check singolarmente ma main si rompe dopo il merge”merge queue, configurabile a livello di repository.