modulo 05 / lezione 28

Correggere senza regressioni

Fix-forward, revert, hotfix branch

Decidere consapevolmente tra correggere in avanti, fare git revert, usare git reset locale o aprire un branch hotfix, valutando rischio e urgenza.

55 min Debugging

In parole semplici

Trovato il bug, identificato il fix. La domanda successiva è come consegnarlo. Tre strade:

  1. Fix-forward: applica il fix sopra lo stato attuale e prosegui.
  2. Revert: invertine il commit problematico, poi indagi con calma.
  3. Hotfix branch: branch dedicato che parte da produzione, riceve solo il fix urgente, viene rilasciato fuori dal normale ciclo.

Sceglierle bene fa la differenza tra fix puliti e incidenti più grandi del problema iniziale.

Parole nuove

  • fix-forward: applicare un nuovo commit che corregge.
  • revert: creare un commit che annulla l’effetto di un commit precedente.
  • hotfix: fix urgente fuori dal normale flusso.
  • release branch: branch da cui parte una release, separato da main.
  • git reset: spostare il puntatore del branch (locale, distruttivo).

Cosa impari

  • Scegliere la strategia in base a urgenza, rischio, ambito del bug.
  • Eseguire git revert e git reset con consapevolezza.
  • Quando aprire un hotfix branch e come integrarlo poi nel main.

Albero decisionale

Il bug è in produzione?
├── No (solo locale o feature branch)
│    → fix-forward o git reset (rilavorare commit)
└── Sì
     ├── Causa nota in un commit recente, fix incerto?
     │    → git revert del commit + indagine con calma
     ├── Causa nota e fix piccolo e sicuro?
     │    → hotfix branch + fix-forward
     └── Causa ignota, urgenza alta?
          → git revert del deploy + indagine

Fix-forward

Caso più comune. Lavori normalmente: scrivi il fix, lo committi, lo merg-i.

git checkout -b fix/carrello-non-persiste
# ... modifiche e test ...
git commit -m "fix(carrello): persistere stato dopo update completo"
git push -u origin fix/carrello-non-persiste
# apri PR, review, merge

Quando funziona:

  • Bug non ancora in produzione.
  • Fix piccolo, sicuro, ben testato.
  • Tempo non critico.

Revert

Quando il commit colpevole è noto ma il fix richiede tempo, invertilo:

git revert <commit-colpevole>

Crea un nuovo commit che annulla le modifiche del precedente. Dopo il revert:

  • Il sistema torna allo stato sano.
  • Hai tempo per indagare senza urgenza.
  • L’autore del commit originale può riproporre il lavoro corretto in una PR separata.

Vantaggi:

  • Sicuro: nessuna distruzione di storia.
  • Tracciabile: git log mostra entrambi i commit.
  • Reversibile: anche il revert si può revertare.

git reset (solo locale!)

Quando il commit colpevole è tuo, locale (non ancora pushato), e vuoi rifarlo da capo:

git reset --soft HEAD~1   # rimuove commit, mantiene modifiche staged
git reset --mixed HEAD~1  # rimuove commit, mantiene modifiche unstaged (default)
git reset --hard HEAD~1   # rimuove commit e modifiche (distruttivo!)

Regola di sicurezza: mai --hard se non sei sicuro. Mai reset di commit già pushati su un branch condiviso (riscrive la storia, rompe i pull degli altri).

Hotfix branch

Per fix urgente in produzione mentre main è in pieno sviluppo:

git checkout main
git pull
git checkout -b hotfix/v2.3.1 v2.3.0   # parto dal tag della release in produzione
# ... fix ...
git commit -m "fix(auth): bypass autorizzazione su endpoint X"
git push -u origin hotfix/v2.3.1
# tag e deploy
git tag v2.3.1
git push --tags
# poi: merge in main per non perdere il fix
git checkout main
git merge hotfix/v2.3.1

Schema:

main          ●──●──●──●──●──● (lavoro in corso, non rilasciabile)
                    \
release v2.3   ●     \
                \     \
hotfix v2.3.1    ●─────● (fix urgente)
                 \    /
                  └──●────────────────────► merge in main

Combinare strategie

A volte la sequenza è:

  1. Revert in produzione subito (contenimento).
  2. Indagine con calma in laboratorio.
  3. Fix forward sul branch di sviluppo.
  4. Hotfix branch che porta il fix definitivo alla release in produzione.

Quattro passi, quattro commit puliti, zero panico.

Sicurezza prima di tutto

Tre regole che salvano carriere:

  1. Mai git push --force su branch condivisi. Riscrive storia altrui.
  2. Mai git reset --hard senza prima git status. Distrugge modifiche non committate.
  3. Mai revert di un merge senza capire -m. Inverte la parte sbagliata.

Quando dubbi, branch nuovo:

git checkout -b prova-reset
# fai esperimenti distruttivi qui
# se va male: torna al branch originale

Esercizio guidato

In una repo didattica:

  1. Aggiungi tre commit. Nel secondo, introduci un bug.
  2. Esegui git revert HEAD~1. Verifica con git log che vedi entrambi i commit.
  3. Resetta lo stato: git reset --hard <commit-iniziale>.
  4. Aggiungi tre commit, nessun bug. Simula: il secondo commit è stato già pushato e qualcuno lo ha integrato.
  5. Prova git reset --hard HEAD~1 e nota che cancelli localmente ma non puoi pushare senza --force. Discuti perché è pericoloso.

Errori frequenti del principiante

  • Reset hard di commit pushati. Rompi i pull degli altri.
  • Revert con --mainline sbagliato. Su merge commit, inverti il pezzo sbagliato.
  • Fix-forward in produzione senza test. Veloce, ma il bug si moltiplica.
  • Hotfix branch dimenticato di tornare in main. Dopo un mese il fix è perso.