我已经阅读了类似场景的一些答案,但不是这个答案。
我需要在git上的特定分支上的两个提交之间生成一个提交列表。因此,应忽略对其他分支的任何提交。知道怎么做吗?
答案 0 :(得分:9)
""之间的概念这里有点模糊,术语"分支"也没有明确定义(通常使用git,即)。让我看看,尽管存在这些问题(对我来说很难:-)),我是否可以保持这么短:
我将假设"在"之间,你的意思是git提交图中的路径的图论理论。例如,假设我们有这个图片段(我不能为节点之间的弧绘制箭头,但假装每个-
,/
或\
都有一个箭头在左侧,以便提交指向左前,下左,或左上,到他们的前任):
o - o
/ \
... - A - o - o - o - B <-- branch-x
\ /
o - o - C <-- branch-y
我已经确定了三个特定提交 - A
,B
和C
- 并提供了两个分支提示名称branch-x
和branch-y
分别指向提交B
和C
。出于git-usefulness的目的,我们还假设标签A
指向提交A
,因此我们不必拼出其SHA-1。
您可以通过三种可能的路径从提交A
获得提交B
。一个从B
开始,一直到顶行,然后下降到中间,然后向左移动到A
。一个从B
开始,直接离开,最终到达A
。最后一次从B
开始,向后退一步,向下,向左,向上和向左,再向左移动到达A
。
如果您没有名为A..branch-x
的标记,Git会为您提供特殊的双点语法A
(或在节点A
的实际SHA-1中替换),对于大多数命令,表示他们应该从B
返回到A
所有可能路径上的所有节点,通常包括节点B
本身,不包括节点A
。这几乎你想要的只是不完全,因为你想要排除在其他分支上提交的提交。
这会带来无法回答的(一般性)问题&#34;哪些提交是在哪个分支上进行的?&#34;
Git试图告诉你这个问题无效:你不应该关心;您应该只关心所有这些提交是否可以从节点B
访问。 Git实际上通常是正确的,但通常&#34;不是&#34;总是&#34;。不幸的是,我还没有找到任何好的方法来描述你应该(或做)关心的时间(实际的好例子会对我试图写的文本有所帮助)。
与此同时,让我们继续吧。从上图中可以清楚地看出,下线的提交都是在branch-y
&#34;上进行的。这里有一个问题,因为似乎清楚,但实际上可能不是 true 。考虑如果我们重新绘制图形会发生什么:
o - o
/ \
... - A - o - o - o - B <-- branch-x
\ /
o
\
o - C <-- branch-y
这次似乎创建branch-y
只是为了保持两个最低提交。 (如果有另一个分支名称指向单独的第三行提交,则更有可能,因为您的原始问题语句表示要排除所有其他分支 - 而不仅仅是分支{{1 - 在这种情况下,这并不重要。)
无论如何,虽然我不太清楚你的意思是&#34; branch&#34;,也不知道你想要给出这个图表的哪些提交,让我们来看看选择器git实际上提供。 可能正是您的意思之一。
我之前提到过&#34;大多数&#34; git命令使用相同的语法说明符。实际上,大多数git命令要么包含来自branch-y
程序的代码,要么只是运行git rev-list
程序,其作用是选择对象(通常是提交对象)以获取要使用的提交ID列表。它也是你想要用于任何脚本的命令。
rev-list
命令has a dizzying number of options,有很多可以帮助进行各种图形遍历。我认为,这里最有趣的两个是--first-parent
和--not
。
--first-parent
让我们先考虑--first-parent
。检查上面的图表(布局:它们可能看起来不同但拓扑结构,它们相同)。请注意,它在 merge 提交,如节点B
本身和节点向左一步B
,路径分叉。这是因为它只有具有多个传出弧的合并提交(这实际上是合并提交的定义:它是一个有两个或更多父节点的节点)。
当git进行合并提交时,它会将各个传出弧编号为多个父节点。第一个弧是特殊的:它是提交时当前分支。也就是说,当你执行git merge <sha-1-or-equivalent>
时,你当时在某个分支上, 1 并且当时当前提交的SHA-1成为&#34;第一个父亲&#34 ;新的合并提交。额外的父母(合并的ID,通常只有一个,但git允许更多)是第二个,第三个,依此类推。
使用--first-parent
标志告诉git只遍历第一父弧。因此,git rev-list --first-parent branch-x
将从提交B
开始,然后找到它的第一个父级(我们无法从上面的图表中看出哪一个是第一个),首先是(并且只有)父,依此类推,一直回到root提交。
这可能是你想要的,也可能不是你想要的(尽管它并没有帮助&#34;&#34之间的概念)。
--not
现在让我们看看--not
标志。 2 通常,git rev-list <SHA-1-ID-or-name>
生成从给定SHA-1可到达的所有提交的集合(解析a首先根据需要命名为ID。也就是说,它遵循回到所有根的所有路径。结果是一组SHA-1 ID。使用--not
会使rev-list
排除这些ID。就其本身而言,这个否定集是没用的,但是当与正常(非否定)集合结合时, 是有用的。事实上,A..B
首先是如何工作的:rev-list
首先生成从B
可到达的所有提交的集合,然后减去可从中获取的所有提交的集合。 A
。
因此,根据您的意思&#34;排除其他分支上的所有提交&#34;,可能就是您想要的是:
git rev-list branch1 --not branch2 branch3 ... branchN
您只需在branch1
之后列出--not
以外的每个分支。
如果我们最后一次查看我们的图表,让我们看看branch-x --not branch-y
选择了哪些提交:
o - o
/ \
... - A - o - o - o - B <-- branch-x
\ /
o - o - C <-- branch-y
提交C
显然可以从branch-y
到达,最下面一行的提交也是如此。 A
右侧的提交也是可以访问的,就像提交A
本身和所有早期提交一样。其余提交 <{1}} <{1}}
branch-y
请注意,branch-x
有B
来包含&#34;剪辑点&#34; (如果我可以称之为那个);添加 o - o
/ \
- o - o - B <-- branch-x
会在原始图表中rev-list
之后放回节点(但--boundary
本身仍然被剪掉)。
(基于您修改过的问题,--boundary
可能就是您想要的,您只需要获取所有分支的列表,git for-each-ref --format '%(refname:short)' refs/heads
是正确的脚本命令。单独列出要保留其节点的一个分支,将其余分支放在A
后面,然后运行A
。)
1 即使您在匿名分支上(换句话说,在&#34;分离的HEAD&#34;模式中),这也是有效的。一些git命令会说你不在任何分支上,但是你仍然在使用与 build 分支相同的git内部。在这种情况下,您当前的分支根本没有名称。
2 技术上--not
只是稍微翻转一下,标记后续的SHA-1或标识符参数被否定。如果他们已经有一个前缀--not
符号,那么他们就会成为正面的#34;参考,否则他们成为负面的参考。因此git rev-list
表示&#34;是x,没有y,是z&#34;而--not
表示&#34;是x,没有y,没有z&#34;并且^
表示&#34;是x,没有y,是z&#34;,例如。
答案 1 :(得分:6)
您可以使用以下命令轻松找到提交列表
git log branch_name commit_x..commit_y
例如,
git log dev HEAD~20..HEAD~10
将显示分支dev
的10 th 到20 th 提交的列表。
您还可以通过git log
的参数过滤所需的任何内容。
您还可以使用git log dev HEAD~20..HEAD~10 >> logs.txt