9

我试图从“git log”输出创建一个线性顺序,但我所有的尝试都失败了。我需要做的是将提交映射到包含该提交的下一个版本。我不能跑

git tag --contains <commit>

对于每个提交,因为我们的存储库包含非常大量的提交(超过 300,000)。

首先我尝试使用

git log --pretty=format:"%ct%H" | sort --key=1,10 

根据提交时间获得线性顺序。但是,这似乎不能产生 100% 准确的结果。这引出了我的第一个问题:

Q1) 当提交被推送到主存储库时,git 如何存储提交时间?它是否以 UTC 格式存储每个提交的当前机器时间?

我还查看了“git help log”,文档指出,默认情况下,git log 按时间顺序列出提交。在我的项目中,我检查了我是否引入了任何错误,但据我所知,代码是正确的,并且 git log 给出的时间顺序不是线性顺序。最后,我的问题是?

Q2) 鉴于 git 不存储修订号,如何从“git log”中获得线性顺序?

谢谢 :)

4

1 回答 1

12

#1:当提交被推送到主存储库时,git 如何存储提交时间?它是否以 UTC 格式存储每个提交的当前机器时间?

来自man git-commit

Git 内部格式
为 [unix timestamp] [timezone offset],其中 [unix timestamp] 是自 UNIX 纪元以来的秒数。[时区偏移] 是与 UTC 的正偏移或负偏移。

基于此,git 内部使用的时间格式是UNIX 纪元时间,包括机器的 UTC 偏移量。

#2:鉴于 git 不存储修订号,如何从“git log”中获得线性顺序?

您使用的方法 ( git log --pretty=format:"%ct%H") 将从所有已合并到当前分支的分支中提取数据。

这使得“线性顺序”有些困难。考虑以下 [来源:git-scm.org ]:

多个分支,预合并

所以,这里我们正在处理几个“主题分支”。然后我们决定保留一些 (dumbideaiss91v2),丢弃其他 ( iss91)。所以我们丢弃C5and C6,保留其他提交,我们的合并后历史看起来像这样 [来源:git-scm.org ]:

合并后

(箭头指向; 提交和的子)。children parentsC14C13C11

所以现在我们有一个单一的HEAD提交,为了争论,我们假设我们将作为 aRELEASE1或其他东西发布。所以,对于这个问题:我们现在如何才能拥有这段历史,提取一个线性的、按时间顺序正确的提交列表?

简单的答案:我不相信你可以 - 或者,如果你这样做,我不相信它会是你想要的。

可以按时间对提交进行线性排序:

git log --pretty=format:"%ct %H" | sort --key=1,10

这将为您提供对应于以下内容的列表:

C1
C2
... snip ...
C13
C14

但是请注意,这实际上不是线性历史!这是因为我们将一些同时创建分支合并在一起。我们无法提取C14(我们的HEAD)父母的线性历史,因为没有一个 - 它是两个分支的孩子,而不是单个提交的孩子,这不是线性关系。

所以,你争辩说,也许我可以只得到一个分支的线性历史?C14 -> C13 ... C3 -> C1, 例如?

这也至少非常困难并且(更有可能)是不可能的。

当我们有多个分支加入(3 路或更多路合并)时,这个问题会更加复杂。这个问题更详细地说明了您无法提取“单个分支”历史的原因 - 当您查看合并提交的父级时,您如何确定哪个是“单个分支”以及哪个是“加入”分支吗?


说了这么多,例如,如果您以图形格式检查这个小存储库的日志:(我确实剪掉了一些没用的提交)


zsh% git log --graph --all --format=format:'%C(blue)%h%C(reset) - %C(green)(%cr)%C(reset)                %C(yellow)%d%C(reset)' --abbrev-commit --date=relative
* 3cf5f06 - (8 weeks ago)  (origin/master, origin/HEAD, master)
* a3a3205 - (4 months ago) 
* c033bf9 - (4 months ago)  (origin/svg)
* ccee435 - (4 months ago) 
*   f08bc1e - (4 months ago) 
|\  
| * 48c4406 - (5 months ago) 
* | 203eeaa - (4 months ago) 
* | 5fb0ea9 - (5 months ago) 
|/  
* 39bccb8 - (5 months ago)

请注意,这段历史按时间顺序排列的;不过,树枝还没有被“压扁”成一个,所以看起来有点时髦。这些提交中的每一个都包含在当前HEAD( master, origin/master) 中。这很明显,因为历史中的两个分支都已合并在一起(合并在f08bc1e)。

#3:我需要做的是将提交映射到包含该提交的下一个版本

如果您对单个提交感兴趣,这个问题,或者您的版本是否被标记会有所帮助。

阅读这个问题,您可能希望将每个提交映射到一个版本;这是很多工作,我对此无能为力 - 不过,我认为您不需要检查每个提交,因为分支将被合并,并且如果线性分支的头部在发布中,线性父母也将是。除非你做过樱桃采摘或类似的事情。

如果您按时间排序,然后检查所有比您的最旧版本更早的提交,记录该提交 ID(如果它包含在最旧版本中,然后是第二旧版本等),并在找到包含它的版本时从列表中删除该提交, 你最多必须检查number of releases* number of commits; 在最坏的情况下,任何版本都没有提交。最好的情况是,发布包含比自身更早的每个提交,即300,000检查。仍然很多,但是(在我幼稚的头脑中)是可行的。

(为冗长的回复道歉)。

于 2012-06-26T17:12:04.407 回答