给定SHA-1哈希值,是否有方法确定提交来自哪个分支?

如果你能告诉我如何使用Ruby Grit实现这一点,那就加分。


当前回答

虽然Dav认为信息没有直接存储是正确的,但这并不意味着你永远都找不到。这里有一些你可以做的事情。

查找提交所在的分支

git branch -a --contains <commit>

这将告诉您其历史中具有给定承诺的所有分支。显然,如果提交已经被合并,这就不太有用了。

搜索回流

如果您正在进行提交的存储库中工作,可以在reflog中搜索该提交的行。gitgc会删除90天以上的反射,因此如果提交时间太长,您将找不到它。也就是说,您可以这样做:

git reflog show --all | grep a871742

找到提交a871742。请注意,您必须使用提交的缩写7个第一位数字。输出应该是这样的:

a871742 refs/heads/completion@{0}: commit (amend): mpc-completion: total rewrite

表明提交是在分支“完成”时进行的。默认输出显示缩写的提交哈希值,因此请确保不要搜索完整的哈希值,否则将找不到任何内容。

git reflog show实际上只是git log-g--abbrev commit--prett=oneline的别名,因此如果您想修改输出格式以使grep可以使用不同的内容,这就是您的出发点!

如果您不是在进行提交的存储库中工作,那么在这种情况下,您所能做的最好的工作就是检查reflog并查找提交首次引入存储库的时间;幸运的是,您获取了它提交到的分支。这有点复杂,因为您不能同时遍历提交树和reflog。您可能需要解析reflog输出,检查每个哈希,看看它是否包含所需的提交。

查找后续合并提交

这取决于工作流,但对于良好的工作流,在开发分支上进行提交,然后将其合并到中。您可以这样做:

git log --merges <commit>..

以查看将给定提交作为祖先的合并提交。(如果提交只合并了一次,那么第一次应该是您要进行的合并;否则,我想您必须检查一些。)合并提交消息应该包含合并的分支名称。

如果您希望能够做到这一点,您可能需要使用--noff选项来gitmerge,以强制创建合并提交,即使在快进情况下也是如此。(不过,不要过于急切。如果过度使用,这可能会让人困惑。)VonC对相关问题的回答有助于阐述这一主题。

其他回答

要查找本地分支机构,请执行以下操作:

grep -lR YOUR_COMMIT .git/refs/heads | sed 's/.git\/refs\/heads\///g'

要查找远程分支,请执行以下操作:

grep -lR $commit .git/refs/remotes | sed 's/.git\/refs\/remotes\///g'

我尝试了以上所有的解决方案,但没有一个对我有效。

以下是迄今为止对我有效的唯一方法(假设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中,“在某个特定分支机构上/由某个分支机构拥有”的承诺不是一个正式的或总是有意义的概念。(以及为什么这个问题没有明确的答案)

gitbranch--contains<ref>是最明显的“瓷”命令。如果您只想使用“管道”命令执行类似的操作:

COMMIT=$(git rev-parse <ref>) # expands hash if needed
for BRANCH in $(git for-each-ref --format "%(refname)" refs/heads); do
  if $(git rev-list $BRANCH | fgrep -q $COMMIT); then
    echo $BRANCH
  fi
done

(此SO答案的交叉点)

除了在所有树中搜索直到找到匹配的哈希值之外,没有。

我处理了同样的问题(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'