Как узнать, указывает ли SHA git на ветку HEAD?

Чтобы избежать ненужных удаленных HEAD при проверке SHA с

> script, я хотел бы проверить ветку вместо этого, если эта SHA является текущим HEAD ветки.

В идеале я хочу передать git SHA, и он возвращает имя ветки, если SHA находится на текущем коннекторе ветвления, или ошибка, если нет.

git describe --all --exact-match <SHA> почти то, что мне нужно, только то, что оно в первую очередь нацелено на теги, и поэтому, если ветка и тег указывают на мой SHA (что часто происходит в наших ветвях выпуска, например), только тег дано. Это не полезно, потому что проверка тега приводит к отсоединенной HEAD (даже если ветвь указывает на тот же SHA).

Заметьте, я не хочу делать git branch --contains - мне не нужно знать, какие ветки содержат мое сообщение.

Если нет команды типа git describe, просто для ветвей, я знаю, что могу перекрестно проверить SHA на SHA на ветку через git show-ref. Однако это не самое элегантное решение.

Я мог бы также сделать git name-rev --name-only <hash>, но мне пришлось бы вручную проверять вывод для символов ~, который чувствует себя неуравновешенным, если там где-то git команда делает то же самое.

Ответ 1

С предстоящим git 2.7 (Q4 2015) вы получите более полную версию git for-each-ref, которые теперь поддерживают --points-at

git for-each-ref --points-at <branch_name>

С документом

--points-at <object>:

Только список указывает, какие точки на данном объекте.

Это позволит проверить, является ли коммит частью этого списка или нет.


См. commit 4a71109, commit ee2bd06, commit f266c91, зафиксировать 9d306b5, commit 7c32834, commit 35257aa, commit 5afcb90,..., commit b2172fd (07 июля 2015 г.) и зафиксировать af83baf (09 июля 2015 г.) Karthik Nayak (KarthikNayak).
(слияние Junio ​​C Hamano - gitster - в commit 9958dd8, 05 октября 2015 г.)

Некоторые функции из "git tag -l" и "git branch -l" были сделаны доступный для "git for-each-ref", чтобы в конечном итоге реализация может быть распределена между всеми тремя, в последующей серии или двух.

* kn/for-each-tag-branch:
  for-each-ref: add '--contains' option
  ref-filter: implement '--contains' option
  parse-options.h: add macros for '--contains' option
  parse-option: rename parse_opt_with_commit()
  for-each-ref: add '--merged' and '--no-merged' options
  ref-filter: implement '--merged' and '--no-merged' options
  ref-filter: add parse_opt_merge_filter()
  for-each-ref: add '--points-at' option
  ref-filter: implement '--points-at' option  

Ответ 2

Вы можете попробовать что-то вроде этого:

git for-each-ref --format="%(refname:short) %(objectname)" 'refs/heads/' |
    grep SHA1 | cut -d " " -f 1

Это должно дать вам список ветвей, которые в настоящее время находятся в ревизии SHA1.

Ответ 3

Если вы собираетесь использовать python, это то, что я сделал бы:

import subprocess

def get_name(target):
    p = subprocess.Popen(['git', 'for-each-ref', 'refs/heads/'], stdout=subprocess.PIPE)
    for line in p.stdout:
        sha1, kind, name = line.split()
        if sha1 != target:
            continue
        return name
    return None

Другой вариант - использовать силу eval для создания словаря:

d = '{' + subprocess.check_output(['git', 'for-each-ref', '--python', '--format=%(objectname): %(refname),', 'refs/heads/']) + '}'
name = eval(d)[sha1]

Ответ 4

В моем случае я хотел знать, указал ли HEAD на ветвь post-checkout, а затем выйдет из 0, если указывает на ветку, или выйдет из ненулевого, если не указывает на ветку, которая скорее всего, отключено состояние HEAD, предполагая, что проверка прошла успешно. git symbolic-ref --short HEAD делает это, а также возвращает имя ветки при указании на один. Очевидно, что есть лучшие решения для того, что нужно OP, но я хотел бросить это на всякий случай, если кто-то захочет воспользоваться этой информацией.

Ответ 5

Я думаю, что одно из решений, может быть, не очень элегантное, но вполне надежное: это список всех ветвей branch --contains $sha, а затем проверить, есть ли git rev-parse $branch == $sha.

Ответ 6

Как насчет grep:

grep -R [sha] .git/refs/heads/

Или, поскольку вы вызываете его из python script, почему бы просто не создать функцию, которая просматривает эти файлы, и возвращает имя или исключение ветки, как вам было нужно.

Ответ 7

попробуйте что-то подобное, чтобы протестировать хеш-подсказку ветки на ваш заданный $sha:

 git branch -a| cut -d " " -f 2,3 | xargs -n 1 git rev-parse | grep $sha

или только локальный

git branch | xargs -n 1 git rev-parse | grep $sha

Ответ 8

Получить только названия веток

Чтобы получить имена веток, на которые ссылаются коммит или тег, я придумал этот .gitconfig:

[alias]
  branch-name = !"git for-each-ref --format=\"%(refname:short) %(objectname)\" 'refs/heads/' | sed -En 's/^(\\S+)\\s+'\"$(git rev-parse \"$1\" 2>/dev/null)\"'$/\\1/p' | grep . || { echo \"$1: not a branch\" >&2; false;}

Например:

$ git branch-head-name da8ecd90
master

Краевые случаи:

  • Вывод равен нулю, если commit-ish не является ветвью.
  • Без аргументов, перечисляет все имена ветвей.

Примечание: псевдоним без .gitconfig строки .gitconfig:

branch-name=!git for-each-ref --format="%(refname:short) %(objectname)" 'refs/heads/' | sed -En 's/^(\S+)\s+'"$(git rev-parse "$1" 2>/dev/null)"'$/\1/p' | grep . || { echo "$1: not a branch" >&2; false;}