Git和日志顺序

9

我试图从 "git log" 输出中创建一个线性顺序,但是我的所有尝试都失败了。我需要做的是将提交映射到包含该提交的下一个版本。我无法运行

git tag --contains <commit>

对于每个提交,由于我们的代码库包含着极其庞大的提交数量(超过 30 万次)。

首先,我尝试使用

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

为了根据提交时间获得线性顺序。然而,这似乎并不能产生100%准确的结果。这带来了我的第一个问题:

Q1) 当提交被推送到主仓库时,Git如何存储提交时间?它是否为每个提交存储当前机器时间(UTC)?

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

Q2) 如何从“git log”中获取线性顺序,考虑到git不存储修订号码?

谢谢 :)


尝试1)git log --pretty=format:"%ct%H" | sort --key=1,10 尝试2)使用git log默认的顺序(时间顺序)。 - leco
如果您愿意,您可以将该评论作为答案添加,这样其他人就可以投票支持它。这也意味着其他人会看到这个问题已经得到了解答。 - Alexander Bird
问题还没有得到回答。我只是发表了评论来澄清一下,在文本中确实提到了我尝试过的方法。之前有人声称我的描述中没有提到这点,所以我加了这个评论只是为了确保一下 :)顺便说一句,那个写评论的人最后删除了他的帖子并且给问题点了踩 :P - leco
1个回答

12

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

man git-commit得知:

Git内部格式
它是[Unix时间戳][时区偏移量],其中[Unix时间戳]是自UNIX纪元以来的秒数。[时区偏移量]是相对于UTC的正或负偏移量。

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

#2: 如何从“git log”中获取一个线性顺序,考虑到git不存储修订号?

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

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

Multiple branches, pre-merge

所以,我们有几个“主题分支”正在被处理。然后我们决定保留一些(dumbideaiss91v2),舍弃其他的(iss91)。因此,我们舍弃了C5C6,保留了其他提交,我们合并后的历史记录如下[source: git-scm.org]:

Post-merge

箭头指向子提交到父提交;C14是提交C13和C11的子提交。
现在我们有一个单一的HEAD提交,为了方便起见,我们假设我们将其发布为RELEASE1或其他什么。那么问题来了:如何从这个历史记录中提取一个线性的、按时间顺序正确的提交列表呢?
简单的答案是:我不认为你可以做到这一点,或者如果你这样做了,我不认为它会是你想要的。
你可以按时间线性排序提交。
git log --pretty=format:"%ct %H" | sort --key=1,10

这将会给你一个相应的列表:

C1
C2
... snip ...
C13
C14

然而,需要注意的是,这并不是一个线性历史!这是因为我们合并了一些同时创建的分支。我们无法提取C14(我们的HEAD)的父级的线性历史,因为它不是单个提交的子级,而是两个分支的子级,这不是一个线性关系。

那么,您可能会问,也许我可以获得一个分支的线性历史?例如C14 -> C13 ... C3 -> C1

即使是这样,最起码也非常困难(更有可能是不可能的)。

当我们有多个分支加入(三方或更多方合并)时,这个问题就变得更加复杂了。这个问题详细介绍了你无法提取“单个分支”历史的原因——当你查看合并提交的父级时,如何确定哪个是“单个分支”,哪个是“加入”的分支?


说了这么多,如果你查看这个小仓库的日志,以图形格式呈现:(我剪掉了一些无用的提交)


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)中。这很明显,因为历史上的两个fork已经合并在一起了(合并在f08bc1e处)。
#3: 我需要做的是将提交映射到包含该提交的下一个版本
如果您对单个提交感兴趣,可以使用这个问题如果您的发布被标记
阅读问题,看起来您可能想将每个提交映射到一个版本;这是很多工作,我无法提供太多帮助 - 我认为您不需要检查每个提交,因为分支将被合并进去,如果线性分支的头部在版本中,则其线性父级也将在其中。除非您已进行了类似挑选樱桃或类似操作。

如果您按时间排序,然后检查所有早于最老版本的提交,记录该提交ID是否包含在最老版本中,然后是第二个最老的版本等等,当您找到包含它的版本时从列表中删除该提交,那么您最多需要检查版本数量 * 提交数量 ; 在最坏的情况下,没有任何提交包含在任何版本中。最好的情况是,版本包含比自身旧的每个提交,这是300,000次检查。尽管仍然很多,但(对我而言)可行。

(抱歉回复较长)。


1
对于深层链接,您将使用页面上最近的锚点,在这种情况下恰好是日期格式部分本身: https://www.kernel.org/pub/software/scm/git/docs/git-commit.html#_date_formats。我使用火狐浏览器扩展程序显示锚点,以便将深层链接添加到我的邮件中。您可以查看源代码并查找锚点,但可能会很繁琐。 - Miserable Variable

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接