Imprimir el nombre simbólico de HEAD

Estoy buscando un command Git que imprima el nombre simbólico de HEAD . Estaba usando este command

 $ git name-rev --name-only HEAD master $ git checkout HEAD~2 $ git name-rev --name-only HEAD master~2 

Sin embargo, noté que no funciona en un nuevo repository

 $ git init $ git name-rev --name-only HEAD Could not get sha1 for HEAD. Skipping. 

Encontré esta solución

 $ git init $ git symbolic-ref --short HEAD master 

Pero esto no funciona en commits más antiguos

 $ git checkout HEAD~2 $ git symbolic-ref --short HEAD fatal: ref HEAD is not a symbolic ref 

Así que ahora tengo esto, que abarca tanto nuevos repos como compromisos anteriores.

 $ git symbolic-ref -q --short HEAD || git name-rev --name-only HEAD master 

Me preguntaba, ¿es esta la mejor manera de hacer esto? Parece que esto debería ser posible con un command.

Usted escribe:

Estoy buscando un command Git que imprima el nombre simbólico de HEAD .

Lo siguiente puede ser suficiente para demostrar que lo que está pidiendo no tiene sentido en todas las situaciones, simplemente porque HEAD no puede asociarse de forma inequívoca con una reference. Sigue leyendo.

Lo que git name-rev hace

En la página de manual de git-name-rev , encontrará la siguiente descripción:

Dado un compromiso, averigua dónde está relacionado con los refs locales. […]

Más específicamente, git name-rev comtesting si <commit-ish> es accesible desde cualquiera de las references locales (procesándolas en order lexicográfico, por ejemplo, develop antes que el master ).

Vamos a examinar qué

 $ git name-rev --name-only <commit-ish> 

lo hace en diferentes casos (la bandera --name-only es incidental aquí, ya que sus efectos son puramente cosméticos).

Caso en el que HEAD no está desconectado

Si HEAD no está desconectado, iow si HEAD está apuntando a una reference válida (llamémoslo myref ), entonces no hay ambigüedad: se está ejecutando

 $ git name-rev --name-only HEAD 

simplemente salidas

 myref 

porque la reference myref está asociada de forma inequívoca con HEAD . Hasta aquí todo bien.

Caso en el que HEAD está separado

En ese caso, las cosas no son tan simples. De hecho, puede haber una o más references de las cuales <commit-ish> es alcanzable, o puede que no haya ninguna.

Caso en el que hay una o más references locales

En la primera reference local encontrada, git name-rev imprime una reference simbólica "relativa", es decir, una revisión de la forma

 <ref>~<n> 

donde <ref> representa la reference local en cuestión, y <n> representa la generación. Por ejemplo, si HEAD apunta directamente a una confirmación que es un abuelo master (el master es la única reference local), entonces

 $ git name-rev HEAD 

devoluciones

 master~2 

Sin embargo, tenga en count que, en el caso de que <commit-ish> sea ​​accesible desde múltiples references, la que devuelve git name-rev es algo arbitraria, ya que solo está dictada por el order lexicográfico (en el que el command verifica references locales).

Caso en el que no existe tal reference local

Es fácil imaginar situaciones en las que <commit-ish> es alcanzable desde ninguna de las references locales. De hecho, aquí hay uno que puedes reproducir en casa (se omite la repetición estándar):

 # set things up $ mkdir test $ cd test $ git init # create a commit $ touch README.md $ git add README.md $ git commit -m "add README" # detach the HEAD (make it point directly to the tip of master, instead of to master itself) $ git checkout $(git rev-parse master) # create a second commit (while in detached-HEAD state) $ printf "foo\n" > README.md $ git commit -am "write 'foo' in README" # attempt to find a symbolic name for HEAD $ git name-rev --name-only HEAD undefined 

Debido a que el DAG de compromiso se ve de la siguiente manera,

 A [master] \ B [HEAD] 

commit B no es alcanzable desde la única reference ( master ); por lo tanto, git name-rev da por vencido y simplemente devuelve undefined .

Conclusión

Dado que no se garantiza que HEAD esté asociado de forma inequívoca a una reference, lo que está pidiendo no tiene sentido :p

Solo quiero agregar mi solución para su caso:

 git symbolic-ref -q --short HEAD || git describe --all --always HEAD 

Esto cubre twigs, tags, cabezas separadas (confirmaciones) y nuevos repositorys. Pero las tags se devolverán como tags/0.1.0 por ejemplo.