首页 > 解决方案 > Git 日志列表提交,不包括从第一个分支中挑选的樱桃

问题描述

例如我有这个提交历史

git历史 在此处输入图像描述

假设在某个时候release1发布到生产环境,几天后,release2分支发布了。

樱桃采摘从未结束过-x争论。

我想获得release2“当时尚未发布”的所有提交,这意味着提交(6,7,8,9)以绿色圆圈标记。

最简单的方法是什么?

github中的存储库示例

更新 1(git 樱桃)

$ git cherry -v release1 release2
- 91785f2be363244a1da4459746fce6a6ea28c2b5 4
- e88de1f8b62213089b300e3143c4caf509b5c13b 5
- 9d23e9c7e6f769c3bbb44ad42bc7b708b4b0a9e6 6
- 6fb71e4406e0b127e06f6e5b145de8a9d39db01e 7
- 6276becc413494b7724a4dd8b852234f4b71e913 8
- 6dd3b5b75222c02c921c9c20bcaee83e1c8be746 9

有了cherry,我似乎仍然得到了 4 和 5 ,它们都是表单大师

更新 2 (--left-right --cherry-mark)

$ git log --left-right --cherry-mark --pretty=oneline --abbrev-commit  release2...release1
= 6dd3b5b 9
= 6276bec 8
> caa4e2f 5
= 0230a1f 4
= 6fb71e4 7
= 9d23e9c 6
= e88de1f 5
= 91785f2 4

这给了我一切,除了 5 是樱桃标记的,我很难解释

使用非空提交更新 3

在最初的尝试中,我使用--allow-empty. 如下所示,它创建了一个空树的哈希。

用真实内容重新创建存储库后,我得到了下面两个答案的期望结果git cherry--left-right --cherry-mark

标签: gitgithub

解决方案


请注意,您的链接存储库包含 15 个完全空的提交。我所说的“空提交”不仅仅是指git commit --allow-empty允许的不更改提交,而是完全空的:每个提交根本没有文件,只有一个提交消息。(更准确地说,每个提交都以空树4b825dc642cb6eb9a060e54bf8d69288fbee4904作为其树。)因此,存储库中的每个提交都与存储库中的每个其他提交等效。

这(主要)解释了为什么您的 update-2 部分显示了它所做的输出: commit与6dd3b5bcommits 等价。难题是为什么提交不与另一个提交配对,因为它也与其他所有提交是补丁等效的。无论如何,这几乎是一个误报的例子,但在这里它实际上更像是一个真正的肯定:这些提交都是相同的,因此可以被丢弃而没有效果。6276bec9d23e9ccaa4e2f


Git 的修订遍历命令 (git loggit rev-list) 可以git patch-id用来标记补丁等效提交。这不是万无一失的,但如果提交是在没有人工干预的情况下精心挑选的,则副本和原始的补丁 ID 将匹配。

要了解如何使用它,请查看or文档(关于此git loggit rev-list部分在两组文档中共享 - 底层实现也是如此 - 所以我只链接到一个)。跳到选项部分--left-right。请注意,--left-right 仅当与对称差异结合使用时才有意义,在这种情况下,这意味着使用语法release1...release2or release2...release1。请注意,这里的两个名称之间有三个点,而不是两个点。

使用三个点 和--left-right,Git 将枚举可从 到达的提交 5 和 4,release1以及可从 到达的两个不同的提交 5 和 4 release2。(当然,Git 会先枚举从 可到达的提交 9、8、7 和 6 ,然后再枚举可从但不可release2到达的 5 和 4。如您所见,调用这四个不同的提交可能是错误的使用相同的两个名称。它们具有不同的哈希 ID 是有原因的:它们是不同的提交。如果您愿意,可以将它们称为and和and ,或者添加发布号,但要给它们不同的名称!)release2release15A5B4A4B5.15.2

到目前为止,这并没有太大帮助:您已经让 Git 向您显示提交 5.1 和 4.1 from release1,标记为<>取决于名称在三个点的哪一侧release1。而且,您有 Git 向您显示提交 9、8、7、6、5.2 和 4.2 from release2,并用另一个标记标记。但这是最重要的起点。您现在可以从切换--left-right--left-only--right-only,告诉 Git不要我显示这两组中的一组,即使您仍在枚举它的所有提交。

有或没有 left 或 right only 选项,您可以添加--cherry-mark, 告诉 Git:在两组中的每个提交上运行。git patch-id当左侧集中的提交与右侧集中的提交具有相同的补丁 ID 时,用等号标记该提交=。否则,用加号标记提交+

因此,在这种情况下,如果您运行:

git rev-list --left-right --cherry-mark --abbrev-commit release2...release1

你会看到(假设提交 9 的哈希 ID 以 等开头999999):

<9999999
<8888888
<7777777
<6666666
=5200000
=4200000
=5100000
=4100000

所以你想要的提交正是那些标有<. 使用release1...release2,您想要的提交正是那些用 标记的>

假设以上所有内容都有意义,现在阅读该--cherry-pick部分

请注意,如果您在挑选时必须解决冲突,则原始提交的补丁 ID 及其副本将不匹配。此过程不会省略此类提交。也有可能得到错误的匹配。这往往发生在仅由以下组成的修复中:例如,移动一些左大括号和右大括号:补丁 ID 不仅通过去除行号,还通过空格来形成。因此,减少两个不同的(通过缩进和行号)大括号更改提交到补丁 ID 会折叠应该不同的提交。因此,我在顶部的声明并不是万无一失的:你可以得到假阴性(樱桃采摘并解决了合并冲突)误报(实际上不同的合并提交)。


推荐阅读