Da Anonimo (non verificato) , 29 Aprile 2026

Introduzione

Gli oggetti sono immutabili e nominati per hash. I riferimenti sono i nomi mutabili leggibili dall'uomo che puntano ad essi. Ogni branch, tag, branch di tracking remoto e HEAD è un ref.

Dove vivono i ref

I ref sono file (o entry nel file packed-refs) sotto .git/refs/:

  • .git/refs/heads/<name>: branch locali.
  • .git/refs/tags/<name>: tag.
  • .git/refs/remotes/<remote>/<name>: branch di tracking remoto.
  • .git/HEAD: il ref corrente.

Ogni ref non simbolico è un file di una riga contenente un hash:

cat .git/refs/heads/main
# a1b2c3d4...

Elencare i ref

git for-each-ref
git for-each-ref refs/tags/
git for-each-ref --format='%(refname:short) %(objectname:short) %(subject)'
git show-ref

Ref simbolici

Un ref simbolico punta a un altro ref invece che a un hash. HEAD è l'esempio canonico:

cat .git/HEAD
# ref: refs/heads/main
git symbolic-ref HEAD
git symbolic-ref refs/remotes/origin/HEAD

Leggere i ref in sicurezza

Passa sempre per il plumbing piuttosto che leggere i file:

git rev-parse HEAD
git rev-parse main
git rev-parse origin/main
git rev-parse v1.0.0^{commit}

Il plumbing gestisce ref impacchettati, ref simbolici e lookup di ref in modo uniforme.

Aggiornare i ref

git update-ref refs/heads/feature/login <sha>
git update-ref -d refs/heads/feature/login           # cancella
git update-ref refs/heads/feature/login <new> <old> # CAS

La forma a tre argomenti è compare-and-set; rifiuta se il valore corrente differisce.

Ref impacchettati

Per performance, Git può impacchettare molti ref in un singolo file .git/packed-refs. git pack-refs --all fa questo; le scritture future vanno comunque a file loose fino al prossimo pack.

Sintassi dei refspec

I remote usano i refspec per mappare tra ref locali e remoti:

+refs/heads/*:refs/remotes/origin/*

Il + iniziale significa "force update". Questa singola riga è ciò che fa popolare a git fetch refs/remotes/origin/.

Il backend reftable

Git moderno (2.45+) include un formato di storage ref alternativo chiamato reftable, sviluppato originariamente per JGit. Reftable memorizza milioni di ref efficientemente in un formato binario log-strutturato e supporta transazioni atomiche su molti ref contemporaneamente. Abilita su un nuovo repo:

git init --ref-format=reftable
git rev-parse --show-ref-format

Per la maggior parte degli utenti il formato classico loose+packed va ancora bene. Reftable brilla sui server e sui monorepo enormi con centinaia di migliaia di ref (es., un ref per pull request).

Gerarchie di ref personalizzate

I ref non devono vivere sotto i quattro namespace standard. Gli strumenti che hanno bisogno dei propri nomi usano gerarchie personalizzate sotto refs/:

  • refs/notes/*: git notes.
  • refs/stash: git stash.
  • refs/replace/*: git replace.
  • refs/bisect/*: stato di git bisect.
  • refs/pull/*/head e refs/merge-requests/*/head: provider di hosting.
git for-each-ref refs/notes/
git for-each-ref refs/replace/

Puoi creare i tuoi finché il nome è un ref valido (niente doppi punti, niente spazi, nessun trattino iniziale).

Errori comuni

Modificare i file ref a mano e finire con un problema di newline finale o un file scritto a metà. Usa git update-ref. Confondere refs/heads/main, main e refs/main; git rev-parse --symbolic-full-name risolve qualsiasi nome corto nella sua forma canonica. Nominare un branch e un tag in modo identico; gli strumenti preferiscono il tag, portando a confusione sottile. Infine, cancellare .git/packed-refs per "fare pulizia"; cancella ref che non erano anche loose. Passa sempre attraverso Git.