git fetch è sempre sicuro. git pull è fetch più merge (o rebase), e quel secondo passaggio è dove le cose vanno storte. Capire la differenza cambia il modo in cui collabori sui branch condivisi.La maggior parte dei developer impara prima git pull e lo usa in modo riflesso. Funziona bene in isolamento, ma su un team con un branch condiviso attivo aggiunge silenziosamente commit di merge alla storia, può fallire a metà operazione se il working tree non è pulito e oscura ciò che è effettivamente arrivato dal remote. Sapere quando usare fetch invece ti ridà il controllo.
Cosa Sono Davvero i Remote Tracking Branch#
Quando cloni un repository, Git crea due tipi di puntatori ai branch:
main– il tuo branch locale, che punta al commit su cui stai lavorando.origin/main– un remote tracking branch, che punta all’ultimo stato conosciuto dimainsul remoteorigin.
origin/main è uno snapshot di sola lettura. Git lo aggiorna ogni volta che esegui git fetch, ma non ci committi mai direttamente. È il modo in cui Git risponde alla domanda “come appare il remote dall’ultima volta che mi sono sincronizzato?”
# Vedi tutti i remote tracking branch
git branch -r
# Confronta il tuo main locale con il ref di tracking remoto
git log main..origin/main --onelinegit fetch: Scarica, Non Integrare#
git fetch contatta il remote, scarica nuovi commit e ref, e aggiorna i tuoi remote tracking branch. Non tocca il tuo working tree né i tuoi branch locali.
# Fetch di tutti i remote
git fetch
# Fetch di un remote specifico
git fetch origin
# Fetch di un branch specifico
git fetch origin mainDopo un fetch puoi ispezionare cosa è arrivato prima di decidere cosa farci:
# Cosa è arrivato?
git log origin/main --oneline -10
# Come sarebbe il merge?
git diff main origin/mainEcco perché git fetch è sempre sicuro. Non può rompere il tuo working tree, non può causare un conflitto di merge e non può interrompere lavoro in corso.
git pull: La Scorciatoia e i Suoi Compromessi#
git pull è una scorciatoia per git fetch seguita da git merge FETCH_HEAD. Eseguirlo su un branch che è divergito dal remote produce un commit di merge:
* a3b2c1d Merge branch 'main' of github.com:org/repo
|\
| * 9f8e7d6 Commit del collega
* | 4c5d6e7 Il tuo commit locale
|/
* 1a2b3c4 Antenato comuneSu un branch condiviso di lunga durata come main, questi commit di merge si accumulano rapidamente e rendono git log difficile da leggere. Complicano anche il bisecting.
git pull –rebase: Mantenere una Storia Lineare#
git pull --rebaseQuesto equivale a git fetch seguito da git rebase origin/main. Invece di creare un commit di merge, riproduce i tuoi commit locali sopra i commit remoti appena scaricati:
* 4c5d6e7 Il tuo commit locale (rebasato)
* 9f8e7d6 Commit del collega
* 1a2b3c4 Antenato comuneLa storia è lineare. Il tuo commit contiene ancora esattamente le modifiche che hai creato, ma ora si trova in cima al lavoro di tutti gli altri.
Puoi rendere questo il comportamento predefinito per tutti i pull:
git config --global pull.rebase truegit pull --rebase fallirà comunque se il tuo working tree ha modifiche non committate che entrano in conflitto con i commit in arrivo. Fai lo stash o committa il tuo lavoro prima di fare pull.
git fetch –prune: Pulizia Bonus#
git fetch --pruneQuesto combina un fetch standard con la rimozione automatica dei remote tracking ref che non esistono più sul remote. Se un collega ha eliminato origin/feature-x su GitHub, --prune rimuove il ref obsoleto origin/feature-x dal tuo repo locale. È una buona abitudine usarlo al posto del semplice git fetch.
Diagramma di Sequenza: fetch vs pull –rebase#
sequenceDiagram
participant L as Locale (main)
participant T as origin/main (tracking)
participant R as Remote (main)
Note over L,R: Un collega pusha un commit sul remote
L->>R: git fetch
R-->>T: Aggiorna origin/main con il nuovo commit
Note over L: Il main locale è invariato. Ispezioni origin/main.
L->>L: git rebase origin/main
Note over L: I tuoi commit riprodotti sopra i nuovi. Storia lineare.
alt Usando git pull --rebase invece
L->>R: git pull --rebase
R-->>T: Fetch: aggiorna origin/main
T-->>L: Rebase: riproduce i commit locali sopra
Note over L: Stesso risultato, un solo comando.
end
Raccomandazione per il Workflow di Team#
Il pattern che scala meglio sui branch condivisi:
# 1. Prima il fetch per vedere cosa c'è
git fetch --prune
# 2. Ispeziona cosa è arrivato
git log main..origin/main --oneline
# 3. Decidi: rebase per storia lineare, merge se serve un merge commit
git rebase origin/main
# oppure
git merge origin/mainFare il fetch prima e decidere dopo ti mantiene in controllo. Non vieni mai sorpreso da un conflitto a metà operazione quando il working tree non è pulito.
Se vuoi approfondire uno qualsiasi di questi argomenti, offro sessioni di coaching 1:1 per ingegneri che lavorano su integrazione AI, architettura cloud e platform engineering. Prenota una sessione (50 EUR / 60 min) o scrivimi a manuel.fedele+website@gmail.com.