gpt4 book ai didi

Git:获取特定分支上两次提交之间的提交

转载 作者:行者123 更新时间:2023-12-02 22:43:01 25 4
gpt4 key购买 nike

我已经阅读了许多类似场景的答案,但不是这个精确的答案。

我需要生成在 git 上特定分支上的两次提交之间发生的提交列表。所以对其他分支所做的任何提交都应该被忽略。知道如何做到这一点吗?

最佳答案

“介于”的概念在这里有点模糊,术语“分支”也没有很好的定义(通常是 git)。尽管有这些问题,让我看看我是否可以保持简短(对我来说很难:-)):

我将假设“之间”是指 git 提交图中路径的图论概念。例如,假设我们有这个图片段(我不能为节点之间的弧绘制箭头,但假设每个 -/\ 在左侧都有一个箭头,以便提交指向直线向左、向下和向左或向上和向左,到他们的前任):

              o - o
/ \
... - A - o - o - o - B <-- branch-x
\ /
o - o - C <-- branch-y

我已经确定了三个特定的提交—— A , B , 和 C — 并提供了两个分支提示名称 branch-xbranch-y指向提交 BC分别。出于 git-usefulness-目的,我们还假设有一个标签 A指向提交 A ,这样我们就不必拼出它的 SHA-1。

您可以通过三种可能的路径到达提交 A来自提交 B .一开始在 B , 上升到顶线,下降回到中间,然后向左移动到 A .一开始在 B ,直接向左走,最终到达 A .最后开始于 B ,后退一步,下左,上左,再左,到达 A .

Git 为您提供了特殊的两点语法, A..branch-x (或者在实际的 SHA-1 中替换节点 A,如果您没有名为 A 的标签),对于大多数命令,这表明它们应该访问来自 B 的所有可能路径上的所有节点。返回 A , 通常包括节点 B本身并排除节点 A .这是 差不多 你想要什么但 不完全 ,因为您想排除在其他分支上进行的提交。

这带来了无法回答的(一般而言)问题“哪些提交是在哪个分支上进行的?”

Git 试图告诉你这个问题是无效的:你不应该关心;您应该只关心所有这些提交都可以从节点 B 访问. Git 实际上通常对此是正确的,但“通常”并非“总是”。不幸的是,我没有找到任何好的方法来描述您何时应该(或确实)关心(实际的好例子对我正在尝试编写的文本会有所帮助)。

与此同时,让我们继续前进。从上图中可以清楚地看出,下一行的提交都是“在 branch-y 上进行的”。这里有一个问题,因为它看起来很清楚,但实际上可能并不正确。考虑一下如果我们重新绘制图形会发生什么:
              o - o
/ \
... - A - o - o - o - B <-- branch-x
\ /
o
\
o - C <-- branch-y

这次很可能是 branch-y创建只是为了保存两个最低的提交。 (如果有另一个分支名称指向单独的第三行提交,则更有可能,尽管因为您的原始问题陈述说排除所有其他分支 - 不仅仅是分支 branch-y - 在这种情况下这并不重要。 )

无论如何,虽然我不太清楚你所说的“分支”是什么意思,也不知道你想要哪个提交给这个图表,让我们来看看 git 实际提供的选择器。有一个重要的可能正是您的意思。

我之前提到过“大多数”git 命令使用相同的语法说明符。事实上,大多数 git 命令要么包含来自 git rev-list 的代码,要么只是运行它。程序,其工作是选择对象(通常是提交对象)以获取要使用的提交 ID 列表。它也是任何类型的脚本编写所需的命令。
rev-list命令 has a dizzying number of options ,许多有助于各种图形遍历。我认为这里最有趣的两个是 --first-parent--not .

使用 --first-parent
让我们考虑 --first-parent第一的。检查上面的图表(任一布局:它们可能看起来不同,但在拓扑上,它们是相同的)。请注意,它是在 merge 提交时,例如节点 B自身和节点左边一步 B ,那条路径 fork 。这是因为它只是具有多个传出弧的 merge 提交(这实际上是 merge 提交的定义:它是具有两个或多个父节点的节点)。

当 git 进行 merge 提交时,它会为多个父项的各个传出弧编号。第一个弧是特殊的:它是提交时的当前分支。也就是说,当你做 git merge <sha-1-or-equivalent> ,当时您在某个分支上,1 并且当时提交的 SHA-1 成为新 merge 提交的“第一个父级”。额外的父级( merge 的 ID,通常只有一个,但 git 允许更多)是第二个、第三个,依此类推。

使用 --first-parent flag 告诉 git 只遍历第一父弧。所以 git rev-list --first-parent branch-x将从提交 B 开始,然后找到它的第一个父级(我们无法从上面的图表中分辨出哪个是第一个),跟随它的第一个(也是唯一的)父级,依此类推,一直回到根提交。

这可能是也可能不是您想要的(尽管它对“介于”的概念没有帮助)。

使用 --not
现在让我们看看 --not flag.2 通常, git rev-list <SHA-1-ID-or-name>生成从给定 SHA-1 可到达的所有提交的集合(根据需要首先将名称解析为 ID)。也就是说,它遵循所有路径回到所有根。结果是一组 SHA-1 ID。使用 --not使 rev-list排除这些 ID。就其本身而言,这个否定集没有用,但是当与正常(非否定)集结合时,它是有用的。其实就是这样 A..B首先作品: rev-list首先生成从 B 可达的所有提交的集合,然后从 A 中减去所有可到达的提交集合.

因此,根据您所说的“排除其他分支上的所有提交”的含义,您可能想要的是:
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 也是可以访问的本身和所有较早的提交。从 branch-y 无法访问剩余的提交,但可以从 branch-x 访问提交 B ,所以结果图是:
              o - o
/ \
- o - o - B <-- branch-x

请注意 rev-list--boundary包括“剪辑点”(如果我可以这样称呼它们);添加 --boundaryA 之后放回节点在原始图中(但 A 本身仍然被剪掉了)。

(根据您修改后的问题, --not 可能是您在这里想要的,您只需要获取所有分支的列表,其中 git for-each-ref --format '%(refname:short)' refs/heads 是正确的脚本命令。分离出要保留其节点的一个分支,把其余的放在 --not 后面,然后运行 ​​ git rev-list 。)

1即使您在匿名分支上(换句话说,在“分离的 HEAD”模式下),这也是有效的。一些 git 命令会说您不在任何分支上,但您仍在使用构建分支的相同 git 内部结构。在这种情况下,您当前的分支根本没有名称。

2技术 --not只是翻转一点,将后续的 SHA-1-or-identifier 参数标记为被否定。如果他们已经有了前缀 ^符号,它们成为“正面”引用,否则它们成为负面引用。因此 x ^y z表示“是 x,否 y,是 z”而 x --not y z表示“是 x,不是 y,不是 z”和 x --not y ^z例如,表示“是 x,否 y,是 z”。

关于Git:获取特定分支上两次提交之间的提交,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34541072/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com