Skip to content

12. Lavorare con i branch

12.1 git branch — elencare, creare, eliminare

Section titled “12.1 git branch — elencare, creare, eliminare”

Git memorizza un branch come semplice riferimento a un commit: la “punta” di una serie di commit, non un contenitore. In pratica i branch isolano linee di sviluppo indipendenti (fix, feature).

Terminal window
git branch # elenca i branch locali (* = corrente)
git branch experiment # crea un branch (ma non ci passa)
git branch -d <branch> # elimina (blocca se ci sono commit non mergiati)
git branch -D <branch> # elimina senza controlli
git branch -m <branch> # rinomina il branch corrente
git branch -a # elenca anche i branch remoti

Creare un branch crea solo un nuovo puntatore all’HEAD corrente: nessun’altra modifica al repository.

12.2 git checkout — estrarre nella working copy

Section titled “12.2 git checkout — estrarre nella working copy”

Git mantiene un riferimento simbolico chiamato HEAD che indica cosa è estratto nella working copy — tipicamente il tip di un branch. git checkout decide cosa caricare nella working copy:

Terminal window
git checkout <branch> # si passa a un branch: i nuovi commit agganciano quel branch
git checkout <commit-o-tag> # si estrae uno snapshot specifico

Estraendo direttamente un commit si entra nello stato di detached HEAD:

Note: switching to '88adbcdf6'.
You are in 'detached HEAD' state. ...
HEAD is now at 88adbcdf6 Change behavior

Prima di estrazione di un commit:

[17452bb]<--[88adbcf]<--[fe78029]<--[6d9c22a]::{main}
^ HEAD

Dopo git checkout 88adbcf la HEAD punta direttamente al commit, senza passare dal branch:

[17452bb]<--[88adbcf]<--[fe78029]<--[6d9c22a]::{main}
^ HEAD

In questo stato eventuali commit non agganciano nessun branch:

[800e2aa]<--[fae892c] <- nessun riferimento a questi commit
[17452bb]<--[88adbcf]<--[fe78029]<--[6d9c22a]::{main}
^ HEAD (di nuovo su main)

Se si torna al branch di partenza senza aver creato un nuovo branch, quei commit non referenziati verranno eliminati dai processi di routine di Git. Per conservarli, creare un branch (es. git switch -c <new-branch>, suggerito nello stesso avviso) o tornare indietro con git switch -.

Combina più sequenze di commit in una cronologia unificata; l’uso più frequente è unire due branch. Preparazione consigliata prima di un merge locale di branch remoti:

  1. individuare il branch che riceve le modifiche (es. main) e quello da unire (es. new-feature);
  2. fare fetch/pull di entrambi;
  3. git checkout main (posizionarsi sul branch che riceve).

Poi:

Terminal window
git merge new-feature

Esistono due modalità di merge:

Fast-forward — quando esiste un percorso lineare dalla HEAD del branch da unire alla HEAD di destinazione: Git non crea alcun commit, limitandosi ad avanzare la HEAD del branch di destinazione.

Terminal window
git checkout -b new-feature main
# ... commit sulla feature ...
git checkout main
git merge new-feature # Fast-forward

Three-way — quando i branch sono divergenti: Git crea un dedicato merge commit, unico tipo di commit con due genitori. Il nome deriva dai tre commit usati per calcolare il risultato: le due HEAD dei branch e il loro antenato comune.

Se la stessa porzione di file è stata modificata in entrambe le history, Git non riesce a completare automaticamente: nasce un conflitto di merge (vedi sezione successiva).

Nota: su piattaforme come GitHub o GitLab il merge tra branch viene spesso eseguito direttamente dalla piattaforma, all’approvazione di una pull/merge request.