Guía9 min

git check-ref-format para coding agents: el nombre es válido, no que la rama exista

Resumen

git check-ref-format valida un refname. --branch imprime el shorthand o fatal 128. Sin flags, 0/1 y silencio. No mira el clone ni github.com. Cero --normalize para 'arreglar' un nombre. No es show-ref. Git 2.50.1.

GitHub
Un refname se valida contra las reglas de Git; el working tree no se mueve

Qué resuelve

Esta pieza se queda en la decisión práctica: qué instalar, qué riesgo agrega y cómo aplicarlo sin romper operación.

git check-ref-format dice si un nombre puede ser una ref. El man (git-check-ref-format(1); git-scm.com/docs/git-check-ref-format HTTP 200, last-modified 2026-08-31; pie del man local Git 2.54.0, 2026-04-19; binario Git 2.50.1 / Apple Git-155) sale 0 si el refname es aceptable. HEAD, index y working tree no se mueven. No crea ramas. No habla con el remoto.

Eso no es show-ref. show-ref --exists responde si la ref está en el clone (0 / 2). check-ref-format responde si el string es un nombre legal. Un path que no existe puede ser 0. Un path que sí existe puede ser 1 si viola las reglas.

GitHub Docs (REST API endpoints for Git references, HTTP 200 2026-09-04): Create a reference pide Contents write y escribe en github.com. Este comando no sustituye eso. Tampoco branch ni tag: esos crean. Aquí preguntas.

Contrato: --branch antes de crear, ramificar 0 / 1 / 128 / 129, cero --normalize para “arreglar”, cero dump.

Un string, cuatro salidas

Sin --branch ni --normalize, el man no imprime el nombre. 0 = válido. Distinto de 0 = no.

PreguntaComandoQué sale
¿Puedo crear esta rama?git check-ref-format --branch nameel shorthand, 0; o not a valid branch name, 128
¿Este path de ref es legal?git check-ref-format refs/heads/namesilencio 0 / silencio 1
¿Un nivel (main)?git check-ref-format --allow-onelevel mainsilencio 0
¿Colapsar //?git check-ref-format --normalize refs/heads//featimprime el path, 0
¿El último switch?git check-ref-format --branch '@{-1}'el nombre, 0; o 128 si no hay

El man: las refs viven en refs/heads/ y refs/tags/. Por default hace falta un /. --allow-onelevel lo relaja. --branch es lo que deben usar los porcelains: acepta el shorthand (feat/foo, no refs/heads/feat/foo) y primero expande @{-n}.

Reglas del man (resumen, no inventar): nada de componente que empiece por . o termine en .lock; nada de ..; nada de control ASCII, espacio, ~, ^, :; nada de ?, *, [ (salvo --refspec-pattern con un *); nada de / al inicio/final ni //; nada de punto al final; nada de @{; nada de \ ; @ solo no es un refname.

--branch es más estricto en un punto: un guion al inicio del nombre de rama está prohibido. El man: un componente de ref puede empezar con - (refs/heads/-bad es 0); git check-ref-format --branch -- -bad no.

Verificado 2026-09-04 (Git 2.50.1 / Apple Git-155):

  • --branch feat/ok → imprime feat/ok, 0. --branch feat/foo igual. --branch main igual.
  • --branch -- -bad → usage 129 (-- cierra opciones; el man pide el shorthand justo después de --branch). --branch -bad'-bad' is not a valid branch name, 128. git branch -- -bad → el mismo fatal 128 y See man git check-ref-format.
  • --branch 128 también: foo..bar, foo.lock, foo@{bar}, foo bar, foo~1, foo^2, foo:bar, foo?, foo*, foo[, foo/, /foo, foo., .foo, foo.lock/bar, -, --, HEAD, vacío.
  • --branch @ → imprime @, 0. git branch '@' crea la ref. No lo uses: @ es token de reflog. --branch HEAD sí es 128.
  • --branch does-not-exist → imprime el nombre, 0. No pregunta al clone. show-ref --exists refs/heads/nope2.
  • --branch '@{-1}' tras mainfeat/ok: imprime main, 0. @{-2} / @{-99}128. Fuera de un repo: @{-1}128; feat/ok sigue 0 (no necesita Git dir).
  • Sin --branch: refs/heads/main 0 silencio. main 1. --allow-onelevel main 0. HEAD 1; --allow-onelevel HEAD 0. refs/heads/-bad 0. refs/heads/foo..bar 1. refs/heads/does-not-exist 0.
  • --normalize 'refs/heads//feat/ok' y '/refs/heads/feat/ok' imprimen refs/heads/feat/ok, 0. --normalize refs/heads/-bad también 0: no aplica la regla del guion de --branch. --print es el alias deprecado.
  • --refspec-pattern refs/heads/feat/* 0. foo/bar*/baz 0. Dos * (foo/bar*/baz*, refs/heads/*/*) 1. Sin el flag, refs/heads/feat/* 1.
  • Sin args / --branch sin nombre / --branch a b → usage 129.

--branch imprime el shorthand o fatal 128; no crea la ref

Lo que el agente sí / no corre

QuieroComandoTrampa
¿Este nombre de rama es legal?git check-ref-format --branch "$name"git branch "$name" y ver qué pasa
¿El path completo es legal?git check-ref-format refs/heads/"$name"Creer que 0 = la rama existe
¿La ref está en el clone?git show-ref --exists -- "refs/heads/$name"Este comando
¿Crear y entrar?switch -c después del 0--normalize “para que pase”

Prohibido en autónomo:

  • Tratar 0 como “la rama existe”. Verificado: does-not-exist es 0. Existencia = show-ref.
  • --normalize para “arreglar” //, un / inicial o un -bad. El man colapsa slashes; no te autoriza a crear refs/heads/-bad.
  • --allow-onelevel para nombres que vas a pasar a branch / switch. Los porcelains usan --branch.
  • --refspec-pattern sobre un nombre de rama. El * es para refspecs de fetch / push, no para git switch -c.
  • Dump de reglas, de .git/refs o de git show-ref al LLM “por si el nombre choca”. Pregunta un string.
  • Crear en github.com con REST Create a reference porque el formato local fue 0. Write en el remoto es otro permiso.
  • Usar @ o HEAD como nombre aunque --branch @ sea 0. HEAD es 128; @ no. No lo conviertas en rama.

Receta (60 segundos)

Solo en un worktree propio:

git status -sb
git check-ref-format --branch "$name" || exit 1
git switch -c "$name" origin/main

Si el ticket es “¿existe ya?”: show-ref --exists, no este comando.

Si el ticket es “¿el tagname es legal?”: el mismo --branch no aplica. Pregunta git check-ref-format "refs/tags/$name" y deja crear a tag.

Cero --normalize. Cero --allow-onelevel. Cero crear si 128.

0 no significa que la ref exista; show-ref --exists es otra pregunta

check-ref-format vs branch vs show-ref

check-ref-format responde si el string es un nombre. branch crea la ref (y ya llama a estas reglas: el fatal apunta a este man). show-ref lista o verifica refs que ya están. rev-parse resuelve un nombre a SHA: un nombre ilegal ni llega.

Un agente que “lee el man y adivina” se salta --branch vs path completo: refs/heads/-bad es 0; --branch -bad es 128; git branch -- -bad es 128.

Checklist

  • Worktree propio. git status -sb. Un nombre por pregunta.
  • Crear rama: --branch "$name". 0 imprime el shorthand. 128 = no crees.
  • Path completo solo para tags/refspecs. Default exige /.
  • Existencia = show-ref --exists. Cero asumir 0.
  • Cero --normalize / --allow-onelevel / --refspec-pattern en autónomo.
  • Cierre = switch -c + PR, no push a main.

FAQ

¿--branch feat/ok crea la rama? No. Imprime feat/ok y sale 0. Crear es switch o branch.

¿Por qué refs/heads/-bad es 0 y --branch -bad es 128? El man: el guion al inicio está prohibido en el shorthand de rama, no en cualquier componente de ref. Verificado. Usa --branch.

¿@{-1} funciona fuera del repo? No. Verificado: 128. Un nombre literal sí: no necesita Git dir.

El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. check-ref-format no es show-ref: valida el string, no el clone.