0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux内核的git历史记录一些最奇怪的事情

Linux爱好者 来源:未知 作者:李倩 2018-08-10 11:22 次阅读

我们通常认为 git merges 有两个父节点。例如,由我写的最新Linux 内核合并操作是提交2c5d955,这是 4.10-rc6 版本发行前准备工作的一部分。它有两个父节点:

2c5d955Merge branch'parisc-4.10-3'of...

|

*- 2ad5d52parisc: Don't use BITS_PER_LONG in use ...

*- 53cd1ad Merge branch 'i2c/for-current'of...

Git 还支持章鱼式的合并,这意味着可以有超过两个父节点的合并。这对于我们那些从事小型项目开发的人来说,这似乎很奇怪:与三四个父节点合并会不会令人感到困惑?这得看情况而定。有时候,一个内核的维护者需要一次同时合并几十个单独的历史记录。一个接着一个的30个合并提交比起单独的一个30路(30个父节点)合并更加令人困惑,特别是当30路合并没有冲突的时候。

章鱼式合并可能比你想象地更常见。在内核的提交历史记录中有649,306个提交。其中 46,930 (7.2%) 个提交是合并提交。在合并提交中,有 1,549 (3.3%) 是章鱼式合并。(截止到我当前的 git HEAD 指向的提交 566cf87 。)

$git log --oneline | wc -l

649306

$git log --oneline --merges | wc -l

46930

$git log --oneline --min-parents=3 | wc -l

1549

作为比较,Rails 的所有提交中的 20% 是合并提交 (12,401/63,111),但没有一个章鱼式合并。Rails 大概更能代表一般的工程; 我认为大多数的 git 用户甚至都不知道章鱼式合并。

现在,显而易见的问题是: 这些章鱼式合并的规模有多大? 在这里每行开头的 “>” 是续行符;这个命令写了总共5行。这篇文章中的所有命令都是我在做实验的时候输入到终端里面的,所以它们未必容易看懂。我对于结果更感兴趣,贴出代码只是为了满足那些好奇的人。

$(git log --min-parents=2 --pretty='format:%h %P' |

>ruby -ne'/^(w+) (.*)$/ =~ $_; puts "#{$2.split.count} #{$1}"' |

>sort -n |

>tail -1)

662cde51f

66 个父节点!这么多的父节点,这个提交到底发生了什么?

这让许多历史记录可视化工具都无法正常运行,引出了 Linus Torvalds 的一个回应:

我刚刚从 Takashi 那收到了一些消息,因此我看到了你的合并提交 2cde51fbd0f3 。这个提交有 66 个父节点。

[…]

它被拉取(pulled)了,并且状况良好,但显然它在 “章鱼式合并很好” 和 “上帝” 之间做到了平衡,这不是一个章鱼式合并,这是一个克苏鲁(一个章鱼头人神的巨人)式的合并。

正如我所看到的,这个有66个父节点的不同寻常的提交在某种程度上只是对于ASoc代码修改的正常合并。ASoc 代表了芯片上的ALSA系统。ALSA系统是音频子系统;“单片系统是集成在单片硅芯片上计算机的术语。综上所述,ASoc 是对嵌入式设备的声音支持系统。

那么这样的合并多久会发生一次呢?永远都不会发生。规模排第二的合并是 fa623d1 ,它仅仅有 30 个父节点。然而,因为足够的背景知识,从 30 到 66 之间的巨大差距并不会令人感到惊讶。

一次 git 提交的父节点的数量大概是一种单侧分布(通常非正式的说法是幂律分布,因为这里对这个不感兴趣,所以不必严格正确)。软件系统的许多属性都属于单侧分布。等一下;我将会生成一个图表来确定…(大量严格的图表确定了)。是的,它确实是单侧分布:

简单地说来, “单侧分布”意味着小事件比大事件多得多,而且大事件的最大规模是没有界限的。内核的提交历史中包含了 45,381 个两个父节点的合并,但仅仅有一个 66个父节点的合并。假如考虑足够多的开发历史记录的话,我们可能会看到多于66个父节点的合并。

单个函数或是单个模块的代码行数也是单侧分布(大多数函数和模块都很小,但是其中一些很大;想想 web app 中的 “User” 类)。同样,对于模块的变化率(大多数模块都不会经常变动,只有其中一些会不断改动;再想想 “User” 类)。这些分布在软件开发中无处不在,而且经常在下面的双对数坐标图中呈直线分布。

对于父节点的数量最大的提交,我们就讨论到这。那么在差异方面的合并又怎样呢?在差异方面,我的意思是被合并的两个分支之间的差异。我们可以通过简单地比较合并节点的父节点,然后统计它们差异的行数来衡量这一点。

例如,如果一个分支一年前从 master 分支分离出去,改变了一行代码,之后被合并回 master 分支,在这段时间内对于 master 分支的所有修改都会被统计到,同样分离出去的分支上的改变也会被统计到。我们可以引出更直观的差异概念,但因为 git 不会保留分支的元数据,所以它们很难或者说是几乎不可能计算出来。

在任何情况下,作为计算差异的起点,下面是最近内核合并的差异:

$git diff$(git log --merges -1 --pretty='format:%P') | wc -l

173

在英语中,这个命令的含义是这样的:“比较最近合并的两个父节点,然后统计差异的行数。”为了找出差异最多的合并,我们可以遍历每个合并提交,用类似的方法统计差异的行数。然后,作为一个测试,我们将搜索所有合并中恰好有 2,000 行差异的分支。

$(git log --merges --pretty="%h" |

whilereadx;do

echo"$(git diff $(git log --pretty=%P $x -1) | wc -l)"$x

done > merges.txt)

$sort -nmerges.txt | grep'b2000b'

20003d6ce33

20007fedd7e

2000f33f6f0

(这个命令需要花费很长的时间运行: 我想大约需要12小时,尽管我已经减少了许多。)

我认为合并的差异大小遵循单侧分布,就像父节点数量的统计一样。所以它应该在双对数坐标图表中显示为一条直线。让我检查一下….对了:

我把差异的大小定在1000行左右(注:前面用2000行,得到的数据太少),否则没有足够的样本来生成有效的曲线。

右下角难看的原因部分是因为量化问题,另一部分是由于缺乏大量的提交导致样本数量较小,与之前的图表情况一样。

现在,显而易见的问题是: 提交历史中差异最大的合并是哪个?

$sort -nmerges.txt | tail -1

22445760f44dd18

22,445,760 行差异!这看起来根本不可能这么大-因为差异的行数比整个内核源代码的行数都大。

Greg Kroah-Hartman 在2016年9月19做了这一提交,当时正处在 4.8-rc6 版本的开发期间。Greg 是 Linus Torvalds 的 “副官” 之一 – 他(Linus)最亲近,最值得信赖的开发者。简单地说,副官们构成了内核 pull request 树中的第一层。Greg 负责维护内核的稳定分支,驱动程序内核,USB 子系统和其他几个子系统。

在更加仔细的研究这个合并之前,我们需要一点背景知识。通常我们把合并作为菱形分支模式(先分支,然后合并,见下图)的一部分:

在2014年,Greg 开始在一个新的仓库开发 Greybus (移动设备总线),这就好像是他创建了一个全新的项目一样。最后,Greybus 的开发工作完成时,它就被合并到了内核中。但因为它是从一个崭新的仓库开始的,所以它和内核的中的其他源代码没有共同的历史记录。所以除了2005年我们公认的初始提交之外,这个合并为内核又添加了一个 “初始提交”。这个仓库现在有两条独立的初始提交,而不是通常的菱形分支模式:

通过查看合并提交的两个父节点中分别存在多少文件,我们可以看到一些蛛丝马迹:

$git log -1f44dd18 | grep'Merge:'

Merge: 93954527398a66

$git ls-tree -r9395452 | wc -l

55499

$git ls-tree -r7398a66 | wc -l

148

一条分支存在大量的文件,因为它包含了整个内核的源文件。而另一条仅仅包含了很少的文件,因为它包含的只是 Greybus 的历史记录。

像章鱼式合并一样,这会让一些 git 用户感到奇怪。但是内核开发人员是专家级的 git 用户,并倾向于放弃使用这个功能,但绝对不是盲目的放弃

最后一个问题:这种情况到底发生了多少次?内核中有多少独立的 “初始化” 提交?事实上是四次:

如果我们要画出这些提交,为了清楚起见,我们忽略所有其他的历史记录,如下图:

这四个提交中的每一个都是离当前内核版本库 HEAD 节点很遥远的祖先节点,并且都没有父节点。从 git 的角度来看,内核历史“开始”了不同的四次,所有的这些提交最终都被合并在一起。

这四个提交中的第一个(在我们输出的底部)是2005年的初始化提交,也就是我们通常认为的初始化提交。第二个是文件系统 btrfs 的开发,它是独立仓库完成的。第三个是 Greybus,同样也是独立仓库完成的,我们之前已经说过。

第四个初始化提交,a101ad9,很奇怪,正如下面看到的:

$git show --oneline --stat a101ad9

a101ad9 Share upstreaming patches

README.md | 2 ++

1file changed,2insertions(+)

它刚创建了一个 README.md 文件。但随后,它就立即被合并到正常的内核历史的提交 e5451c8 中了!

$git show e5451c8

commit e5451c8f8330e03ad3cfa16048b4daf961af434f

Merge: a101ad93cf42ef

Author: Laxman Dewangan

Date: Tue Feb2319:37:082016 +0530

为什么有人会创建一个只包含两行文本的 README 文件的初始化提交,然后立即合并到主线的历史记录中呢?我想不出任何理由,所以我怀疑这是一个意外!但它没有造成任何危害;它只是很奇怪。(更新:这是个意外,Linus用他一贯的方式回应了。)

顺便提一句,这也是历史记录中差异数量排第二的提交,仅仅因为它是一个不相关提交的合并,就像我们仔细研究过的 Greybus 的合并一样。

现在你知道了:Linux 内核的 git 历史记录一些最奇怪的事情。一共有 1,549 个章鱼式合并,其中有一个是拥有 66 个父节点的提交。差异最多的合并有 22,445,760 行差异,尽管它有点技术性因为它和仓库的其他部分没有公共的历史记录。内核拥有四个独立的初始化提交,其中一个是失误导致的。尽管上面的这些都不会出现在绝大多数的 git 仓库中,但是所有的这些功能都是在 git 的设计范围之内的。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 芯片
    +关注

    关注

    450

    文章

    49614

    浏览量

    417078
  • Linux
    +关注

    关注

    87

    文章

    11123

    浏览量

    207885
  • 嵌入式设备
    +关注

    关注

    0

    文章

    109

    浏览量

    16903

原文标题:Linux 内核 Git 历史记录中,最大最奇怪的提交信息是这样的

文章出处:【微信号:LinuxHub,微信公众号:Linux爱好者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    鸿蒙原生应用元服务开发-Web历史记录导航

    /向后浏览上个/下历史记录。 在下面的示例中,点击应用的按钮来触发前端页面的后退操作。 // xxx.ets import web_webview from \'@ohos.web.webview
    发表于 05-20 15:14

    怎样清除protel99se的历史文件记录

    只要创建新文件,就会在文件菜单留下记录,即使文件已删除,文件菜单里仍然会有历史记录,怎样清除这个历史记录呢?请老师解答,万分感谢!
    发表于 04-23 17:30

    LabVIEW的输入框可以做成带历史记录的吗?

    请问,LabVIEW的数值控件可以做成像百度样的,可以有历史记录显示并可以选择那样的吗?
    发表于 10-28 10:09

    Cosmic STM8编译器修订历史记录

    Cosmic STM8编译器修订历史记录?以上来自于谷歌翻译以下为原文 Cosmic STM8 compiler revision history?
    发表于 05-13 16:07

    创建蓝牙盒子在订单历史记录中看不到

    你好,我想订购个样品来尝试建立个自己的蓝牙盒子。在我发送请求后,它会显示您的订单已成功创建,但我无法在订单历史记录中看到它。关闭选项卡后,它会再次显示图表中的项目。以上来自于谷歌翻译以下为原文
    发表于 07-22 06:55

    LINUX怎么清除历史记录命令

    目的很简单,就是清除linux下的历史命令linux 下输入history 命令显示历史敲过的命令
    发表于 07-25 07:45

    Agilent 81200数据发电机/分析仪平台更改和修正历史记录

    81200 SW更改和增强历史记录(Apr02)
    发表于 08-28 06:33

    带中移动模组M6315的机器上传到云平台的历史记录的时间和机器本身记录的时间不致,

    带中移动模组M6315的机器上传到云平台的历史记录的时间和机器本身记录的时间不致,有些相差个多月,是什么原因?要从哪些方向去分析?
    发表于 10-22 16:56

    追踪项目历史

    历史记录的方式取决于您是在Altium Designer中查看历史记录还是通过网页浏览器在DigiPCBA工作区中查看历史记录。鉴于在每个区域可以访问不同的功能,接下来就让我们简单了解
    发表于 03-30 10:07

    富士康收入创造历史记录 并未受苹果新手机高价格影响

    富士康集团位高管表示,无论是三季度还是今年前三季度,富士康的收入都创造了历史记录
    的头像 发表于 10-14 09:57 4585次阅读

    2018年DRAM销售额创历史记录新高 同比增长39%

    据报道,市场研究公司DRAMeXchange在3月4日报道称,全球DRAM市场去年的销售额达到99,655百万美元,同比增长39%,创历史记录新高。
    发表于 03-10 09:58 1452次阅读

    微软Edge浏览器更新:已支持同步历史记录

    据Windows Central报道,微软Edge浏览器刚刚获得了项新功能,用户可以跨设备打开浏览历史记录
    的头像 发表于 11-18 09:24 1933次阅读

    QQ、Tim等存在读取浏览器历史记录现象

    日前,有网友反馈QQ、Tim等软件会读取本地浏览器的历史记录资料,引发大家对隐私、安全等问题的担忧。
    的头像 发表于 01-19 11:13 2213次阅读
    QQ、Tim等存在读取浏览器<b class='flag-5'>历史记录</b>现象

    uModule解决方案组合主板修订历史记录(DC1758A)

    uModule解决方案组合主板修订历史记录(DC1758A)
    发表于 04-19 11:05 4次下载
    uModule解决方案组合主板修订<b class='flag-5'>历史记录</b>(DC1758A)

    鸿蒙开发实例:【demo-搜索历史记录

    HarmonyOs-demo-搜索历史记录
    的头像 发表于 03-26 22:40 465次阅读
    鸿蒙开发实例:【demo-搜索<b class='flag-5'>历史记录</b>】