如何找到git SHA指向分支HEAD?

时间:2013-09-30 17:54:18

标签: git

为了避免在使用(python)脚本检出某个git SHA时出现不必要的分离HEAD,我想检查一个分支,如果该SHA恰好是分支的当前HEAD。

理想情况下,我想为git提供SHA,如果SHA在分支的当前提示上,则返回分支名称,否则返回错误。

git describe --all --exact-match <SHA> 非常接近是我需要的,只是它主要针对标签,所以如果分支标签指向我的SHA (例如,经常发生在我们的发布分支中),只给出了标记。这没用,因为签出标签会导致分离的HEAD(即使分支指向同一个SHA)。

注意,我不想git branch --contains - 我不需要知道哪些分支包含我的提交。

如果没有像git describe那样的命令,只是对于分支,我知道我可以通过git show-ref对分支SHA进行交叉检查。不过,这不是最优雅的解决方案。

我也可以做git name-rev --name-only <hash>,但是我必须手动检查~个字符的输出,如果有一个git命令可以做同样的事情,这会感觉不自在。

8 个答案:

答案 0 :(得分:8)

您可以尝试这样的事情:

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

这应该会为您提供当前位于修订版SHA1的分支列表。

答案 1 :(得分:2)

如果您打算使用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]

答案 2 :(得分:2)

随着即将推出的git 2.7(2015年第4季度),您将获得更完整版的git for-each-ref,现在支持--points-at

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

使用doc:

--points-at <object>:
  

仅列出指向给定对象的引用。

这将允许检查提交是否是该列表的一部分。

请参阅commit 4a71109commit ee2bd06commit f266c91commit 9d306b5commit 7c32834commit 35257aacommit 5afcb90,..., commit b2172fd(2015年7月7日)和commit af83baf(2015年7月9日)Karthik Nayak (KarthikNayak)
Junio C Hamano -- gitster --合并于commit 9958dd8,2015年10月5日)

  

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  

答案 3 :(得分:1)

对于我的情况,我想知道HEAD是否指向分支 post-checkout 然后如果指向分支则退出0,或者如果不指向分支则退出非零,假设结账成功,很可能是分离的HEAD状态。 git symbolic-ref --short HEAD执行此操作,并在指向分支时返回分支的名称。显然,有更好的解决方案可以满足OP的需求,但我想把它放在以防万一有人想要利用这些信息。

答案 4 :(得分:1)

仅获取分支名称

要获取提交或标记引用的分支名称,我想出了这个.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不是分支,则输出为null。
  • 不带任何参数,列出所有分支名称。

注意:不带.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;}

答案 5 :(得分:0)

我认为解决方案之一,可能不是很优雅,但非常可靠:列出所有分支branch --contains $sha,然后检查git rev-parse $branch == $sha

答案 6 :(得分:0)

grep:

怎么样?
grep -R [sha] .git/refs/heads/

或者,因为您是从python脚本调用它,为什么不创建一个搜索这些文件的函数,并根据需要返回分支名称或异常。

答案 7 :(得分:0)

尝试这样的方法来测试每个分支提示哈希对你给定的$ 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