【发布时间】:2018-05-26 09:54:30
【问题描述】:
我使用git log tag1..tag2 来查看tag1 和tag2 之间的提交(其中tag1 是旧标签,tag2 是新标签)。我希望看到在tag1 和tag2 之间进行的提交,但我也看到在tag1 的日期之前进行的提交。为什么会这样?
【问题讨论】:
我使用git log tag1..tag2 来查看tag1 和tag2 之间的提交(其中tag1 是旧标签,tag2 是新标签)。我希望看到在tag1 和tag2 之间进行的提交,但我也看到在tag1 的日期之前进行的提交。为什么会这样?
【问题讨论】:
您遇到了这样一个事实:commit1..commit2 并不意味着人们最初认为它意味着什么。事实上,这个符号只是commit2 ^commit1 的简写。这意味着:查找可从commit2 访问的提交,不包括提交commit1 和可从commit1 访问的提交。
这个“可到达”的概念有点棘手。我喜欢把它想象成“油漆暂时呈红色或绿色”。像往常一样,红色意味着停止,绿色意味着去。我们从最新的提交开始并向后工作。红色油漆覆盖绿色油漆:停止的提交保持停止状态,即使有其他东西可以让它继续。
考虑一个像这样的提交图,新的提交总是添加在右边:
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.0、1.1和2.0(带有v的标签)版本,分别对应于提交H2、H5和J2。名称mainline 指向J 之后的某个提交,因此如果我们使用名称mainline 作为green/go,我们会将其所有提交降为J,然后继续返回到I、H ,G,等等。不过,我们永远不会“再次正确”,所以我们永远不会将任何额外的Jn 或Hn 提交绿色。类似地,如果我们选择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。这一切都很好,并且可能是您所期望的。
但是这个图表是非常线性的。假设我们在图中有一些 fork-and-merge 行为:
G--H
/ \
...--E--F K--L <-- branchname
\ /
I--J
我们选择提交L 开始,J 停止。我们把J涂成红色,而I和F和E等等也都是红色的。然后我们绘制L绿色、K绿色、H绿色和G绿色。 F 已经是红色(或者如果我们在绿色之后再做红色,则会被红色覆盖)。那么,最终的提交列表是L、K、H 和G,尽管在某种意义上G 可能早于J。诀窍在于G 无法从J 访问。 Git 根本不按日期进行:它是按提交图中的可达性进行的。
另请参阅 my answer 至 List commits between 2 commit hashes in git,以及更普遍的 Think like (a) Git。
【讨论】: