Распечатать символическое имя для HEAD
Я ищу команду Git, которая напечатает символическое имя для HEAD
, Я использовал эту команду
$ git name-rev --name-only HEAD
master
$ git checkout HEAD~2
$ git name-rev --name-only HEAD
master~2
Однако я заметил, что это не работает на новом хранилище
$ git init
$ git name-rev --name-only HEAD
Could not get sha1 for HEAD. Skipping.
Я нашел этот обходной путь
$ git init
$ git symbolic-ref --short HEAD
master
Но это не работает на старых коммитах
$ git checkout HEAD~2
$ git symbolic-ref --short HEAD
fatal: ref HEAD is not a symbolic ref
Так что теперь у меня есть это, которое охватывает как новые репо, так и старые коммиты
$ git symbolic-ref -q --short HEAD || git name-rev --name-only HEAD
master
Мне просто интересно, это лучший способ сделать это? Такое ощущение, что это должно быть возможно с помощью одной команды.
2 ответа
Ты пишешь:
Я ищу команду Git, которая напечатает символическое имя для
HEAD
,
Следующего может быть достаточно, чтобы продемонстрировать, что то, что вы просите, не имеет смысла во всех ситуациях, просто потому, что HEAD
не может быть однозначно связан с одной ссылкой. Читать дальше.
Какие git name-rev
делает
в git-name-rev
man-страницу, вы найдете следующее описание:
Получив коммит, выясните, где он находится по отношению к местным ссылкам. [...]
Более конкретно, git name-rev
проверяет, <commit-ish>
доступен из любой локальной ссылки (путем обработки их в лексикографическом порядке, например, develop
до master
).
Давайте посмотрим, что
$ git name-rev --name-only <commit-ish>
делает в разных случаях (--name-only
флаг здесь случайный, так как его действие чисто косметическое).
Случай, в котором HEAD
не отделен
Если HEAD
не оторван, если я HEAD
указывает на действительный ref (давайте назовем его myref
), то тут двусмысленности нет
$ git name-rev --name-only HEAD
просто выводит
myref
поскольку myref
ссылка однозначно связана с HEAD
, Все идет нормально.
Случай, в котором HEAD
отделен
В этом случае все не так просто. На самом деле, может быть одна или несколько ссылок, из которых <commit-ish>
достижимо, или вообще не может быть.
Случай, в котором есть одна или несколько таких локальных ссылок
При первом обнаружении такой локальной ссылки, git name-rev
печатает "относительную" символьную ссылку, то есть ревизию формы
<ref>~<n>
где <ref>
обозначает местную ссылку, о которой идет речь, и <n>
обозначает поколение. Например, если HEAD
указывает непосредственно на коммит, который является прародителем master
(master
будучи единственной местной ссылкой), то
$ git name-rev HEAD
возвращается
master~2
Обратите внимание, однако, что в случае <commit-ish>
достижимо из нескольких ссылок, одна из которых возвращена git name-rev
является несколько произвольным, так как он продиктован только лексикографическим порядком (в котором команда проверяет локальные ссылки).
Случай, в котором нет такой локальной ссылки
Легко представить себе ситуации, в которых <commit-ish>
достижимо ни от одной из местных ссылок. На самом деле, вот тот, который вы можете воспроизвести дома (стандартный вывод отсутствует):
# 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
Поскольку коммит DAG выглядит следующим образом,
A [master]
\
B [HEAD]
совершить B
не доступен из единственной ссылки (master
); следовательно, git name-rev
сдается и просто возвращается undefined
,
Заключение
Так как HEAD
не гарантируется однозначная привязка к одной ссылке, то, что вы просите, не имеет смысла :p
Просто хочу добавить мое решение для вашего случая:
git symbolic-ref -q --short HEAD || git describe --all --always HEAD
Это касается веток, тегов, отдельных головок (коммитов) и новых репозиториев. Но теги будут возвращены как tags/0.1.0
например.