Git 两个标签之间的日志显示提交早于标签?

Git log between two tags showing commits older than tags?

我正在使用 git log tag1..tag2 查看 tag1tag2 之间的提交(其中 tag1 是旧标签,而 tag2 是较新)。我希望看到在 tag1tag2 之间进行的提交,但我也看到了在 tag1 日期之前进行的提交。为什么会这样?

您 运行 明白 commit1..commit2 并不像人们最初认为的那样。事实上,这个符号只是 shorthand for commit2 ^commit1。这意味着:查找可从 commit2 访问的提交,排除提交 commit1 和可从 commit1.

访问的提交

这个"reachable from"概念有点棘手。我喜欢将其视为 "paint commits red or green temporarily"。像往常一样,红色表示停止,绿色表示走。我们从最新的提交开始并向后工作。红色油漆覆盖绿色油漆:停止提交保持停止状态,即使其他东西会让它继续。

考虑像这样的提交图,其中新提交总是添加在右侧:

                  tag:v2.0
                     |
                     v
                J1--J2   <-- release/2
               /
...--G--H--I--J--...   <-- mainline
         \
          H1--H2--H3--H4--H5   <-- release/1
               ^           ^
               |           |
            tag:v1.0    tag:v1.1

在这里,我们发布了版本 1.01.12.0(带有 v 的标签),对应于提交 H2H5J2 分别。名称 mainline 指向 J 之后的某个提交,因此如果我们将名称 mainline 用作 green/go,我们将其所有提交都归结为 J,并且继续向后 IHG 等。不过,我们从不 "go right again",所以我们从不将任何额外的 JnHn 提交涂成绿色。类似地,如果我们选择 H2 来绘制红色,我们会绘制 H2,然后是 H1,然后是 H,然后是 G,依此类推向左,但我们从不向右移动,所以我们不会触及 I 或任何更右边的东西。

查看提交 v1.0..v1.1,您将看到提交 H5,然后是 H4,然后是 H3。它们被涂成绿色(从 v1.1 又名 H5 开始),从未涂成红色(从 v1.0 又名 H2 开始)。查看 v1.1..v2.0,您将看到 J2,然后是 J1,然后是 J,然后是 I,然后是 H。没关系,这可能是您所期望的。

但是这张图是非常线性的。假设我们在图中有一些分叉合并行为:

          G--H
         /    \
...--E--F      K--L   <-- branchname
         \    /
          I--J

我们选择提交 L 开始,J 停止。我们把J涂成红色,IFE等也都是红色的。然后我们画L绿色,K绿色,H绿色,G绿色。 F 已经是红色(或者如果我们在绿色之后做红色,将会被红色覆盖)。那么,最终的提交列表是 LKHG,尽管在某种意义上 G 可能早于 J。诀窍在于 G 无法从 J 访问。 Git 根本不按日期进行:它按提交图中的可达性进行。

另见 my answer to List commits between 2 commit hashes in git, and more generally, Think like (a) Git