11

为了避免在使用(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. 不过,这不是最优雅的解决方案。

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

4

8 回答 8

8

你可以尝试这样的事情:

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

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

于 2013-09-30T18:19:42.883 回答
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]
于 2013-09-30T23:19:49.670 回答
2

随着即将推出的 git 2.7(2015 年第四季度),您将获得更完整git for-each-ref的 .--points-at

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

使用文档:

--points-at <object>:

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

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


请参阅提交 4a71109提交 ee2bd06提交 f266c91提交 9d306b5提交 7c32834提交 35257aa提交 5afcb90,...,提交 b2172fd(2015 年 7 月 7 日)和提交 af83baf(2015 年 7 月 9 日),作者为Karthik Nayak(KarthikNayak
(由Junio C Hamano 合并gitster——提交 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  
于 2015-10-07T09:16:24.027 回答
1

对于我的情况,我想知道 HEAD是否指向结帐后的分支,然后如果指向分支则退出 0,或者如果不指向分支则退出非零,假设结帐成功,这很可能是分离的 HEAD 状态. git symbolic-ref --short HEAD这样做并在指向一个时返回分支的名称。显然,对于 OP 的需求,有更好的解决方案,但我想抛出这个以防万一有人想利用这些信息。

于 2017-08-03T01:01:36.157 回答
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;}
于 2019-06-12T14:18:16.060 回答
0

怎么样 grep :

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

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

于 2013-09-30T18:24:35.290 回答
0

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

于 2013-09-30T18:07:40.527 回答
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
于 2013-10-01T17:02:35.340 回答