Por Anónimo (no verificado) , 29 Abril 2026

Introducción

Los objetos son inmutables y nombrados por hash. Las referencias son los nombres mutables y legibles que apuntan a ellos. Cada branch, tag, branch de seguimiento remoto y HEAD es una ref.

Dónde viven las refs

Las refs son archivos (o entradas en el archivo packed-refs) bajo .git/refs/:

  • .git/refs/heads/<name>: branches locales.
  • .git/refs/tags/<name>: tags.
  • .git/refs/remotes/<remote>/<name>: branches de seguimiento remoto.
  • .git/HEAD: la ref actual.

Cada ref no simbólica es un archivo de una línea que contiene un hash:

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

Listando refs

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

Refs simbólicas

Una ref simbólica apunta a otra ref en lugar de a un hash. HEAD es el ejemplo canónico:

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

Leyendo refs de forma segura

Siempre pasa por plumbing en lugar de leer archivos:

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

El plumbing maneja packed refs, refs simbólicas y búsquedas de refs uniformemente.

Actualizando refs

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

La forma de tres argumentos es compare-and-set; rechaza si el valor actual difiere.

Packed refs

Por rendimiento, Git puede empaquetar muchas refs en un solo archivo .git/packed-refs. git pack-refs --all hace esto; las escrituras futuras siguen yendo a archivos sueltos hasta el próximo pack.

Sintaxis de refspec

Los remotos usan refspecs para mapear entre refs locales y remotas:

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

El + inicial significa "force update". Esta única línea es lo que hace que git fetch popule refs/remotes/origin/.

El backend reftable

Git moderno (2.45+) incluye un formato alternativo de almacenamiento de refs llamado reftable, originalmente desarrollado para JGit. Reftable almacena millones de refs eficientemente en un formato binario log-estructurado y soporta transacciones atómicas a través de muchas refs a la vez. Habilítalo en un nuevo repo:

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

Para la mayoría de usuarios el formato clásico loose+packed sigue siendo válido. Reftable brilla en servidores y en monorepos enormes con cientos de miles de refs (p.ej., una ref por pull request).

Jerarquías de refs personalizadas

Las refs no tienen que vivir bajo los cuatro namespaces estándar. Las herramientas que necesitan sus propios nombres usan jerarquías personalizadas bajo refs/:

  • refs/notes/*: git notes.
  • refs/stash: git stash.
  • refs/replace/*: git replace.
  • refs/bisect/*: estado de git bisect.
  • refs/pull/*/head y refs/merge-requests/*/head: proveedores de hosting.
git for-each-ref refs/notes/
git for-each-ref refs/replace/

Puedes crear las tuyas propias mientras el nombre sea una ref válida (sin puntos dobles, sin espacios, sin guión inicial).

Errores comunes

Editar archivos de ref a mano y terminar con un problema de salto de línea final o un archivo escrito a medias. Usa git update-ref. Confundir refs/heads/main, main y refs/main; git rev-parse --symbolic-full-name resuelve cualquier nombre corto a su forma canónica. Nombrar un branch y un tag de forma idéntica; las herramientas entonces prefieren el tag, llevando a confusión sutil. Finalmente, eliminar .git/packed-refs para "limpiar"; elimina las refs que no estaban también sueltas. Siempre pasa por Git.