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

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


当前回答

2013年12月更新:

sschuberth注释

gitwhat分支(Perl脚本,见下文)似乎不再被维护。合并时的git是一种用Python编写的替代方法,对我来说非常有用。

它基于“查找包含特定提交的合并提交”。

git when-merged [OPTIONS] COMMIT [BRANCH...]

查找提交合并到一个或多个分支的时间。查找将commit带入指定BRANCH的合并提交。具体来说,在包含commit作为祖先的BRANCH的第一个父历史上查找最早的提交。


原答复2010年9月:

Sebastien Douche刚刚推了推(在这个SO回答之前16分钟):

gitwhatbranch:发现提交所在的分支,或者它是如何到达命名分支的

这是Seth Robertson的Perl脚本,看起来很有趣:

简介

git-what-branch [--allref] [--all] [--topo-order | --date-order ]
[--quiet] [--reference-branch=branchname] [--reference=reference]
<commit-hash/tag>...

概述告诉我们(默认情况下)提交和合并的最早因果路径,以使请求的提交到达指定的分支。如果直接在指定的分支上进行提交,那么这显然是最早的路径。所谓最早的因果路径,我们指的是最早合并到命名分支的路径,即提交时间(除非指定了拓扑顺序)。性能如果许多分支(例如数百个)包含提交,系统可能需要很长时间(对于Linux树中的特定提交,探索一个分支需要8秒,但有超过200个候选分支)来跟踪每个提交的路径。选择要检查的特定引用分支引用标记将快数百倍(如果您有数百个候选分支)。示例

 # git-what-branch --all 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4
 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 first merged onto master using the following minimal temporal path:
   v2.6.12-rc3-450-g1f9c381 merged up at v2.6.12-rc3-590-gbfd4bda (Thu May  5 08:59:37 2005)
   v2.6.12-rc3-590-gbfd4bda merged up at v2.6.12-rc3-461-g84e48b6 (Tue May  3 18:27:24 2005)
   v2.6.12-rc3-461-g84e48b6 is on master
   v2.6.12-rc3-461-g84e48b6 is on v2.6.12-n
   [...]

该程序不考虑樱桃选择感兴趣的提交的影响,只考虑合并操作。

其他回答

2013年12月更新:

sschuberth注释

gitwhat分支(Perl脚本,见下文)似乎不再被维护。合并时的git是一种用Python编写的替代方法,对我来说非常有用。

它基于“查找包含特定提交的合并提交”。

git when-merged [OPTIONS] COMMIT [BRANCH...]

查找提交合并到一个或多个分支的时间。查找将commit带入指定BRANCH的合并提交。具体来说,在包含commit作为祖先的BRANCH的第一个父历史上查找最早的提交。


原答复2010年9月:

Sebastien Douche刚刚推了推(在这个SO回答之前16分钟):

gitwhatbranch:发现提交所在的分支,或者它是如何到达命名分支的

这是Seth Robertson的Perl脚本,看起来很有趣:

简介

git-what-branch [--allref] [--all] [--topo-order | --date-order ]
[--quiet] [--reference-branch=branchname] [--reference=reference]
<commit-hash/tag>...

概述告诉我们(默认情况下)提交和合并的最早因果路径,以使请求的提交到达指定的分支。如果直接在指定的分支上进行提交,那么这显然是最早的路径。所谓最早的因果路径,我们指的是最早合并到命名分支的路径,即提交时间(除非指定了拓扑顺序)。性能如果许多分支(例如数百个)包含提交,系统可能需要很长时间(对于Linux树中的特定提交,探索一个分支需要8秒,但有超过200个候选分支)来跟踪每个提交的路径。选择要检查的特定引用分支引用标记将快数百倍(如果您有数百个候选分支)。示例

 # git-what-branch --all 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4
 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 first merged onto master using the following minimal temporal path:
   v2.6.12-rc3-450-g1f9c381 merged up at v2.6.12-rc3-590-gbfd4bda (Thu May  5 08:59:37 2005)
   v2.6.12-rc3-590-gbfd4bda merged up at v2.6.12-rc3-461-g84e48b6 (Tue May  3 18:27:24 2005)
   v2.6.12-rc3-461-g84e48b6 is on master
   v2.6.12-rc3-461-g84e48b6 is on v2.6.12-n
   [...]

该程序不考虑樱桃选择感兴趣的提交的影响,只考虑合并操作。

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

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

作为一个实验,我制作了一个提交后挂钩,它在提交元数据中存储关于当前签出的分支的信息。我还略微修改了gitk以显示该信息。

你可以在这里查看:https://github.com/pajp/branch-info-commits

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