给定SHA-1哈希值,是否有方法确定提交来自哪个分支?
如果你能告诉我如何使用Ruby Grit实现这一点,那就加分。
给定SHA-1哈希值,是否有方法确定提交来自哪个分支?
如果你能告诉我如何使用Ruby Grit实现这一点,那就加分。
当前回答
gitcheckout<SHA>->将使您进入分离的HEAD状态。
git rev parse--abbrev ref HEAD->将打印HEAD,因此此命令在这种状态下不起作用。
现在我们处于分离HEAD状态,可以使用以下命令获取分支名称。PS:如果您没有处于分离的HEAD状态,这将不起作用!
git branch -a --contains HEAD | sed -n 2p | awk '{ printf $1 }'
瞧!现在您有了分支名称。
其他回答
我处理了同样的问题(Jenkins多分支管道)——只有提交信息,并试图找到该提交最初来源的分支名称。它必须适用于远程分支,本地副本不可用。
这是我的工作:
git rev-parse HEAD | xargs git name-rev
也可以剥离输出:
git rev-parse HEAD | xargs git name-rev | cut -d' ' -f2 | sed 's/remotes\/origin\///g'
TL;博士:
如果您关心shell退出状态,请使用以下内容:
branch current-当前分支的名称分支名称-干净的分支名称(每行一个)分支名称-确保仅从分支名称返回一个分支
分支名称和分支名称都接受提交作为参数,如果没有给出,则默认为HEAD。
在脚本编写中有用的别名
branch-current = "symbolic-ref --short HEAD" # https://stackoverflow.com/a/19585361/5353461
branch-names = !"[ -z \"$1\" ] && git branch-current 2>/dev/null || git branch --format='%(refname:short)' --contains \"${1:-HEAD}\" #" # https://stackoverflow.com/a/19585361/5353461
branch-name = !"br=$(git branch-names \"$1\") && case \"$br\" in *$'\\n'*) printf \"Multiple branches:\\n%s\" \"$br\">&2; exit 1;; esac; echo \"$br\" #"
只能从一个分支进行提交
% git branch-name eae13ea
master
% echo $?
0
输出至STDOUT退出值为0。
可从多个分支访问的提交
% git branch-name 4bc6188
Multiple branches:
attempt-extract
master%
% echo $?
1
输出至STDERR退出值为1。
由于退出状态,可以安全地构建这些。例如,要获取用于获取的远程:
remote-fetch = !"branch=$(git branch-name \"$1\") && git config branch.\"$branch\".remote || echo origin #"
如果OP试图确定在创建特定提交时分支所遍历的历史(“在给定SHA-1哈希值的情况下,找出提交来自哪个分支”),那么如果没有reflog,Git对象数据库中就没有任何记录显示哪个命名的分支绑定到了什么提交历史。
(我将此作为回复评论的回复发布。)
希望这个脚本能说明我的观点:
rm -rf /tmp/r1 /tmp/r2; mkdir /tmp/r1; cd /tmp/r1
git init; git config user.name n; git config user.email e@x.io
git commit -m"empty" --allow-empty; git branch -m b1; git branch b2
git checkout b1; touch f1; git add f1; git commit -m"Add f1"
git checkout b2; touch f2; git add f2; git commit -m"Add f2"
git merge -m"merge branches" b1; git checkout b1; git merge b2
git clone /tmp/r1 /tmp/r2; cd /tmp/r2; git fetch origin b2:b2
set -x;
cd /tmp/r1; git log --oneline --graph --decorate; git reflog b1; git reflog b2;
cd /tmp/r2; git log --oneline --graph --decorate; git reflog b1; git reflog b2;
输出表明,没有任何方法知道使用“Add f1”的提交是来自远程克隆/tmp/r2的分支b1还是b2。
(此处为输出的最后一行)
+ cd /tmp/r1
+ git log --oneline --graph --decorate
* f0c707d (HEAD, b2, b1) merge branches
|\
| * 086c9ce Add f1
* | 80c10e5 Add f2
|/
* 18feb84 empty
+ git reflog b1
f0c707d b1@{0}: merge b2: Fast-forward
086c9ce b1@{1}: commit: Add f1
18feb84 b1@{2}: Branch: renamed refs/heads/master to refs/heads/b1
18feb84 b1@{3}: commit (initial): empty
+ git reflog b2
f0c707d b2@{0}: merge b1: Merge made by the 'recursive' strategy.
80c10e5 b2@{1}: commit: Add f2
18feb84 b2@{2}: branch: Created from b1
+ cd /tmp/r2
+ git log --oneline --graph --decorate
* f0c707d (HEAD, origin/b2, origin/b1, origin/HEAD, b2, b1) merge branches
|\
| * 086c9ce Add f1
* | 80c10e5 Add f2
|/
* 18feb84 empty
+ git reflog b1
f0c707d b1@{0}: clone: from /tmp/r1
+ git reflog b2
f0c707d b2@{0}: fetch origin b2:b2: storing head
gitcheckout<SHA>->将使您进入分离的HEAD状态。
git rev parse--abbrev ref HEAD->将打印HEAD,因此此命令在这种状态下不起作用。
现在我们处于分离HEAD状态,可以使用以下命令获取分支名称。PS:如果您没有处于分离的HEAD状态,这将不起作用!
git branch -a --contains HEAD | sed -n 2p | awk '{ printf $1 }'
瞧!现在您有了分支名称。
我尝试了以上所有的解决方案,但没有一个对我有效。
以下是迄今为止对我有效的唯一方法(假设HEAD处于合理位置):
git log --branches --source | grep <sha>
#or if you also care about remotes
git log --branches --remotes --source | grep <sha>
分支的名称应位于行的末尾。
从文档中
--来源打印出命令行上给定的引用名称,通过该名称可以实现每次提交。
因此,这可能会根据HEAD所在的位置而改变,但对我来说,将HEAD放在主分支的最新提交时产生了我预期的结果。
用gitk进行目视检查——所有这些都可能有帮助。它为每个提交都有一个“分支”字段,但它显示了“可以到达”该提交的所有分支,而不一定是该提交所在的分支。请参见此处
旁白:
值得一提的是,这个问题有点用词不当。与其他SVC不同,在git中的分支只是指向提交历史/图中位置的临时指针。他们不“拥有”提交,也不“由”提交组成。它们本质上只是标签,在签出标签时更新到您推送的任何提交。因此,分支不是一系列提交,而是指向一系列提交的末端/末端的指针。因此,提交不“属于”或“来自”分支,它们只是图中的节点。
那么我们到底在这里做什么?我们正在使用可达性的概念。如果我们从每个分支指向的提交开始(“分支”的“结束”),并回溯历史,我们可以找到/达到哪些提交?我们说提交是“在”一个分支上,如果找到它们的唯一方法是在该特定分支上开始搜索。
注意,这不是一个稳定的事情。如果我们突然合并、重命名或重新设置分支的基础,那么我们的分支将发生变化,其中哪些提交可以通过(因此“on”)访问。这就是为什么在git中,“在某个特定分支机构上/由某个分支机构拥有”的承诺不是一个正式的或总是有意义的概念。(以及为什么这个问题没有明确的答案)