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

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


当前回答

例如,要发现c0118fa提交来自redesign_interactions:

* ccfd449 (HEAD -> develop) Require to return undef if no digits found
*   93dd5ff Merge pull request #4 from KES777/clean_api
|\
| * 39d82d1 Fix tc0118faests for debugging debugger internals
| * ed67179 Move &push_frame out of core
| * 2fd84b5 Do not lose info about call point
| * 3ab09a2 Improve debugger output: Show info about emitted events
| *   a435005 Merge branch 'redesign_interactions' into clean_api
| |\
| | * a06cc29 Code comments
| | * d5d6266 Remove copy/paste code
| | * c0118fa Allow command to choose how continue interaction
| | * 19cb534 Emit &interact event

您应该运行:

git log c0118fa..HEAD --ancestry-path --merges

然后向下滚动以找到最后一次合并提交。即:

commit a435005445a6752dfe788b8d994e155b3cd9778f
Merge: 0953cac a06cc29
Author: Eugen Konkov
Date:   Sat Oct 1 00:54:18 2016 +0300

    Merge branch 'redesign_interactions' into clean_api

使现代化

或者只需要一个命令:

git log c0118fa..HEAD --ancestry-path --merges --oneline --color | tail -n 1

其他回答

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

简单的答案是Git不存储提交的分支的名称。试图重建这些信息的技巧似乎在所有情况下都不起作用。

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

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

虽然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对相关问题的回答有助于阐述这一主题。

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 #"