1 03-Branching-Merging
Emanuele edited this page 2025-12-25 13:16:41 +01:00

03 - Branching e Merging

Comandi per gestire branch (rami paralleli di sviluppo) e unire le modifiche.


git branch

Sintassi

git branch                    # Lista branch
git branch <nome>             # Crea branch
git branch -d <nome>          # Elimina branch
git branch [opzioni]

Spiegazione

Gestisce i branch del repository. I branch permettono sviluppo parallelo di feature senza interferire con il codice principale.

Esempi pratici

Listare tutti i branch locali:

git branch

Output:

  develop
* main
  feature-login

L'asterisco * indica il branch corrente.

Listare tutti i branch (locali + remoti):

git branch -a
# oppure
git branch --all

Output:

* main
  develop
  remotes/origin/main
  remotes/origin/develop
  remotes/origin/feature-api

Listare solo branch remoti:

git branch -r

Creare nuovo branch:

git branch feature-notifiche

Crea branch ma NON ci switcha.

Creare branch da commit specifico:

git branch hotfix abc123

Eliminare branch (merged):

git branch -d feature-completata

⚠️ Funziona solo se il branch è già stato merged.

Forzare eliminazione branch (anche non merged):

git branch -D feature-abbandonata

⚠️ Usa con cautela, perdi commit non merged!

Rinominare branch corrente:

git branch -m nuovo-nome

Rinominare branch diverso:

git branch -m vecchio-nome nuovo-nome

Vedere ultimo commit per branch:

git branch -v

Output:

  develop         abc123 Update dependencies
* main            def456 Fix login bug
  feature-login   789abc Add OAuth support

Branch merged/non-merged in main:

git branch --merged main        # Branch già merged
git branch --no-merged main     # Branch non ancora merged

Workflow tipico branch

# 1. Crea branch per nuova feature
git branch feature-dark-mode

# 2. Switcha al nuovo branch
git checkout feature-dark-mode

# 3. Lavora, commit...
git add .
git commit -m "Implement dark mode toggle"

# 4. Torna a main
git checkout main

# 5. Merge della feature
git merge feature-dark-mode

# 6. Elimina branch
git branch -d feature-dark-mode

Opzioni comuni

Opzione Descrizione
-a, --all Tutti i branch (locali+remoti)
-r Solo remoti
-d Elimina (safe)
-D Elimina (force)
-m Rinomina
-v Verbose (con ultimo commit)
--merged Solo branch merged
--no-merged Solo non merged

Note

  • Branch principale: main o master
  • Convenzioni nomi: feature/, bugfix/, hotfix/
  • Branch sono "puntatori" leggeri a commit

git checkout / git switch

Sintassi

# Vecchio modo (checkout)
git checkout <branch>
git checkout -b <nuovo-branch>

# Nuovo modo (switch - Git 2.23+)
git switch <branch>
git switch -c <nuovo-branch>

Spiegazione

git checkout: Comando storico multi-funzione (cambia branch, ripristina file).
git switch: Comando nuovo dedicato solo al cambio branch (più chiaro).

Esempi pratici

Cambiare branch:

# Vecchio
git checkout develop

# Nuovo (preferito)
git switch develop

Creare e switchare branch in un comando:

# Vecchio
git checkout -b feature-api

# Nuovo (preferito)
git switch -c feature-api

Tornare al branch precedente:

git switch -
# oppure
git checkout -

Switchare a remote branch:

git switch feature-api
# Git crea automaticamente branch locale tracciando origin/feature-api

# Equivalente esplicito:
git switch -c feature-api origin/feature-api

Checkout di commit specifico (detached HEAD):

git checkout abc123

⚠️ Sei in "detached HEAD", commit fatti qui si perdono se non crei branch.

Per esplorare commit vecchi senza rischi:

# 1. Vai al commit
git checkout abc123

# 2. Esplora, compila, testa...

# 3. Torna a branch normale
git switch main

Checkout file da branch diverso:

git checkout develop -- config.ini

Prende config.ini dal branch develop e lo copia nel branch corrente.

git checkout vs git switch vs git restore

Git 2.23+ ha diviso checkout in due comandi più chiari:

Comando Uso Esempio
git switch Cambiare branch git switch main
git restore Ripristinare file git restore file.txt
git checkout Entrambi (legacy) Vecchio modo

Raccomandazione: usa switch e restore (più chiari).

Workflow cambio branch

# Verifica stato pulito
git status

# Se hai modifiche non salvate:
# Opzione 1: Commit
git commit -am "WIP: work in progress"

# Opzione 2: Stash (salva temporaneamente)
git stash

# Cambia branch
git switch develop

# (lavora su develop...)

# Torna a branch precedente
git switch main

# Ripristina stash (se usato)
git stash pop

Opzioni comuni

Opzione Descrizione
-b (checkout) / -c (switch) Crea + switcha
- Branch precedente
-f, --force Forza (scarta modifiche locali)
--detach Detached HEAD

Note

  • Non puoi switchare con modifiche uncommitted (usa stash o commit)
  • git switch è il modo moderno, usa quello
  • Detached HEAD: utile per esplorare, non per lavorare

git merge

Sintassi

git merge <branch>
git merge [opzioni] <branch>

Spiegazione

Unisce le modifiche di un branch in un altro. Integra la cronologia di due branch divergenti.

Esempi pratici

Merge base:

# Sei su main, vuoi mergere feature
git switch main
git merge feature-login

Merge fast-forward:

git merge develop

Se main non ha nuovi commit, Git sposta semplicemente il puntatore (fast-forward).

Output:

Updating abc123..def456
Fast-forward
 src/auth.py | 10 ++++++++++
 1 file changed, 10 insertions(+)

Merge con commit di merge:

git merge --no-ff feature-api

Crea sempre commit di merge anche se possibile fast-forward.

Merge con messaggio custom:

git merge feature-payment -m "Merge feature payment con gateway Stripe"

Merge senza commit automatico:

git merge --no-commit feature-test
# Verifica modifiche
git status
# Poi commit manuale
git commit -m "Merge feature test dopo review"

Annullare merge in corso:

git merge --abort

Gestire Merge Conflicts

Quando Git non riesce a unire automaticamente:

git merge feature-conflitto

Output:

Auto-merging src/app.py
CONFLICT (content): Merge conflict in src/app.py
Automatic merge failed; fix conflicts and then commit the result.

Workflow risoluzione conflitti:

# 1. Vedi file in conflitto
git status

# 2. Apri file e trova conflitti
# File conterrà:
<<<<<<< HEAD
codice nel branch corrente
=======
codice nel branch da mergere
>>>>>>> feature-conflitto

# 3. Risolvi manualmente (scegli/combina)
# Rimuovi marker <<<<, ====, >>>>

# 4. Staging file risolti
git add src/app.py

# 5. Completa merge
git commit

Tool visuale per conflitti:

git mergetool

Vedere file in conflitto:

git diff --name-only --diff-filter=U

Strategie di Merge

Merge normale (recursive):

git merge feature

Strategia default, funziona nella maggior parte dei casi.

Merge "ours" (ignora loro modifiche):

git merge -X ours feature

In caso di conflitto, prende sempre la versione del branch corrente.

Merge "theirs" (preferisci loro modifiche):

git merge -X theirs feature

Workflow completo Feature Branch

# 1. Crea feature branch da main
git switch main
git pull origin main
git switch -c feature-newsletter

# 2. Lavora sulla feature
git add .
git commit -m "Add newsletter subscription"

# 3. Aggiorna da main (se altri hanno pushato)
git switch main
git pull origin main
git switch feature-newsletter
git merge main  # Porta novità di main nella feature

# 4. Merge feature in main
git switch main
git merge feature-newsletter

# 5. Push
git push origin main

# 6. Cleanup
git branch -d feature-newsletter

Opzioni comuni

Opzione Descrizione
--no-ff Sempre commit di merge
--ff-only Solo fast-forward
--squash Squash commit in uno
--abort Annulla merge in corso
-X ours/theirs Strategia conflitti
--no-commit Non committa automaticamente

Note

  • Prima di merge: git pull origin main (aggiorna)
  • Conflitti sono normali, non aver paura
  • Merge preserva cronologia completa

git rebase

Sintassi

git rebase <branch>
git rebase [opzioni] <branch>

Spiegazione

Riscrive la cronologia spostando commit sopra un altro branch. Crea cronologia lineare (più pulita di merge).

⚠️ REGOLA D'ORO: Non rebasare commit già pushati e condivisi!

Esempi pratici

Rebase base:

# Sei su feature, vuoi rebassare su main aggiornato
git switch feature-api
git rebase main

Git "stacca" i tuoi commit di feature, aggiorna a main, poi "riattacca" i commit sopra.

Rebase interattivo (riscrivere storia):

git rebase -i HEAD~3

Apre editor con ultimi 3 commit. Puoi:

  • pick = mantieni commit
  • reword = cambia messaggio
  • edit = modifica commit
  • squash = unisci con precedente
  • fixup = come squash ma scarta messaggio
  • drop = elimina commit

Esempio interattivo:

pick abc123 Add login form
squash def456 Fix login validation
pick 789abc Add tests

Risultato: primi due commit uniti in uno.

Continuare rebase dopo risolvere conflitti:

# Conflitto durante rebase
git add file-risolto.txt
git rebase --continue

Saltare commit problematico:

git rebase --skip

Annullare rebase:

git rebase --abort

Rebase su remote branch:

git rebase origin/main

Merge vs Rebase

Merge (preserva cronologia):

       A---B---C feature
      /         \
 D---E---F---G---H main

Rebase (cronologia lineare):

                 A'--B'--C' feature
                /
 D---E---F---G main

Quando usare Merge:

  • Feature branch pubbliche condivise
  • Vuoi preservare cronologia esatta
  • Lavoro in team

Quando usare Rebase:

  • Pulizia branch locale prima di push
  • Cronologia lineare leggibile
  • Feature branch personali

Workflow rebase per feature pulite

# 1. Sviluppo locale su feature
git switch feature-auth
git add .
git commit -m "WIP: auth logic"
git commit -m "WIP: tests"
git commit -m "WIP: fix bug"

# 2. Squash commit prima di push (pulizia)
git rebase -i HEAD~3
# (squash tutti in un commit pulito)

# 3. Aggiorna feature con ultimi cambiamenti main
git fetch origin
git rebase origin/main

# 4. Push (prima volta forza con -f)
git push origin feature-auth -f

# 5. Merge in main (da GitHub/Forgejo PR)

Opzioni comuni

Opzione Descrizione
-i Interattivo
--continue Continua dopo conflitto
--skip Salta commit
--abort Annulla
--onto Rebase su branch diverso
--autosquash Auto-squash fixup commits

Note

  • MAI rebasare commit pubblici/pushati
  • Rebase riscrive SHA commit
  • Utile per cronologia pulita prima PR
  • Più complesso di merge, serve pratica

🔗 Collegamenti


📝 Riepilogo comandi

# BRANCH
git branch                      # Lista branch
git branch feature              # Crea branch
git branch -d feature           # Elimina branch
git branch -a                   # Tutti (locali+remoti)

# SWITCH
git switch main                 # Cambia branch
git switch -c feature           # Crea + switcha
git switch -                    # Branch precedente

# CHECKOUT (legacy)
git checkout main               # Cambia branch
git checkout -b feature         # Crea + switcha

# MERGE
git merge feature               # Merge feature in branch corrente
git merge --no-ff feature       # Sempre commit di merge
git merge --abort               # Annulla merge

# REBASE
git rebase main                 # Rebase su main
git rebase -i HEAD~3            # Interattivo (ultimi 3)
git rebase --continue           # Continua dopo conflitto
git rebase --abort              # Annulla rebase