Introduzione
Un branch di tracking remoto è un ref locale che rispecchia un branch su un remote. Vivono sotto refs/remotes/<remote>/ e vengono aggiornati da git fetch (e operazioni che implicano fetch, come git pull e git clone). Non si committa direttamente su di essi.
Da dove vengono
Il refspec predefinito per origin è:
+refs/heads/*:refs/remotes/origin/*
Quindi quando il server ha refs/heads/main, il tuo clone ottiene refs/remotes/origin/main. Il + iniziale significa "force update".
Elencare
git branch -r
git branch -a # locali + tracking remoto
git branch -vv # mostra l'upstream dei locali
Collegare un branch locale a uno
git switch feature/login # crea automaticamente il locale da origin/feature/login
git switch -c mine origin/feature/login # esplicito
git branch -u origin/main # imposta l'upstream del branch corrente
git branch --unset-upstream
Il collegamento upstream guida l'ahead/behind di git status, e i target predefiniti per git push e git pull.
Pruning
I branch di tracking remoto non spariscono quando il branch remoto viene cancellato. Puliscili:
git fetch --prune
git remote prune origin
git config --global fetch.prune true
Lo speciale HEAD remoto
Ogni remote ha un HEAD simbolico che indica il suo branch predefinito:
git symbolic-ref refs/remotes/origin/HEAD
git remote set-head origin --auto # interroga il server
Questo è ciò che fa risolvere origin da solo a origin/main (o qualsiasi default).
Diff contro un branch di tracking remoto
git fetch
git log HEAD..origin/main --oneline # cosa c'è a monte
git log origin/main..HEAD --oneline # cosa c'è solo localmente
git diff @{u} # vs upstream
@{u} (o @{upstream}) è la scorciatoia per l'upstream configurato del branch corrente.
Comportamento di push
Il default push.default = simple pusha il branch corrente al suo upstream con lo stesso nome. Se pushi un branch senza upstream e hai push.autoSetupRemote = true (Git 2.37+), l'upstream viene creato automaticamente.
Dettagli dei refspec
Il refspec di fetch per un remote può essere personalizzato per scaricare ref aggiuntivi o per mapparli diversamente. Per esempio, per scaricare anche i ref delle PR di GitHub e MR di GitLab:
git config --add remote.origin.fetch '+refs/pull/*/head:refs/remotes/origin/pr/*'
git config --add remote.origin.fetch '+refs/merge-requests/*/head:refs/remotes/origin/mr/*'
Il + iniziale significa "force update", necessario perché i ref delle PR possono muoversi (rebase sul branch della PR). Dopo il fetch, le PR del server appaiono come ref locali origin/pr/*, pronte per git switch -c review/<n> origin/pr/<n>.
Errori comuni
Provare a fare git checkout origin/main e modificare; ti mette in detached HEAD perché origin/main è read-only. Crea invece un tracking branch. Dimenticare git fetch e essere fuorviati da conteggi ahead/behind stantii. Trattare i branch di tracking remoto come se pushare su di essi aggiornasse il server; sono mirror locali. Usa git push origin main. Infine, cancellare origin/main con git branch -dr e assumere che il branch del server sia sparito; non lo è. Usa git push origin --delete main e solo quando intendi farlo davvero.