LWN:Git archive 生成文件遇到了Hyrum法则!

关注了就能看到更多这么棒的文章哦~

Git archive generation meets Hyrum's law

By Jonathan Corbet
February 2, 2023
DeepL assisted translation
https://lwn.net/Articles/921787/

1 月 30 日,GitHub 博客发布了一条简短的通知,称该网站生成的归档文件(如 tarballs)的 checksum 校验和数值刚刚发生了变动。GitHub 的工程师们似乎没有意识到这种改变的后果,其实只要熟悉打包系统或海勒姆法则(HYrum's law)的人来说,后果是完全可以预见的。这些校验和数值是 build 系统在深度依赖的内容,而这些 build 系统在改动生效后立即无法运转了;由此产生的下巴掉到地板上的声音在全世界都能听到。这一改动目前已被回退掉了,但值得关注一下 GitHub 是如何导致这种大量的 build 系统的出错的,以及为什么这种变动今后几乎肯定还会再次发生。

GitHub 的一个广泛使用的功能就是针对任何一个 commit 来下载当前仓库状态的归档文件;构建系统经常会使用它来获取某个希望下载的软件包的特定版本。具体实现上来说,这个归档文件是在收到请求后由 git archive 子命令来创建出来的。大多数 build 系统会将生成的归档文件与另外独立存储的一个校验和进行比较,从而确保归档文件符合预期,也就是没有被破坏;如果校验和不匹配,当前的 build 构建过程将被中止。因此,当 GitHub 生成的压缩包的校验和突然发生变化时,世界各地的 build 系统就开始报错了。

不出所料,人们开始抱怨。GitHub 的员工(也是 Git 的主要贡献者)Brian M. Carlson 最初的反应是完全不理解:

我想说的是,这种做法从来都不是正确的做法,我们从来没有保证过归档文件的校验和不变,Git 也从来没有保证过这一点。我很抱歉,大家在这里碰到了麻烦,而且我们也没有很清晰地沟通过这个方面,但我们的政策在四年多的时间里都是没有改变过的。

可以说,这个答案并没有被人们所接受。例如,Wyatt Anderson 说:

在出错之后去修复受此改动影响的无法正常工作的构建系统、以及在整个软件生态系统中重新发布这些归档文件,这一切所需要的人工成本都可能可以治愈癌症了。请考虑尽快回退这一改动。

呼声越来越高,大约过了两个小时,Matt Cooper(GitHub 的另一名员工)才宣布这个改动被撤销了,目前是这样。"我们回退掉了这个改动,会在未来更好地提前针对这类改动进行沟通(包括给出时间节点)"。build 工作恢复了正常,和平再次降临了。

The source of the problem

GitHub 的开发人员并不是突然某天早上醒来就打算搞出一个破坏大量 build 系统的计划的;相反,他们所做的只是升级了内部使用的 Git 版本。2022 年 6 月,René Schedar 将 git archive 改为使用了一个内部实现的 gzip 压缩算法,而不是调用独立的 gzip 程序。这一改动在 Git 2.38 版本中落地了,从而使 Git 放弃了对 gzip 的依赖,更容易支持跨操作系统的压缩,并且需要更少的 CPU 时间来完成压缩数据的动作。

这也导致 git archive 对文件的压缩方式有了改变。虽然未压缩的数据是相同的,但压缩后的数据不一样,因此校验和也变得不一样了。一旦这一变动在 GitHub 的生产系统中落地,那么所生成的压缩包的校验和就会突然改变。GitHub 回退了这一改动,要么是恢复到旧版本的 Git,要么就是明确配置来使用独立的 gzip 程序,于是这个问题立即消失了。

到目前为止,Git 邮件列表上的讨论相对比较平静。Eli Schwartz 首先提出了一个建议,即 Git 应该暂时将其默认值改回使用外部 gzip 程序,然后使用内部压缩器来实现 "v2 版本的 archive 格式"。利用某种启发式方法,从而让 Git archive 总是默认为在某个截止日期之前的 commit 都使用旧的格式。这将确保对旧的 archive 的持续兼容性,但将这种启发式方法引入 Git 的观点并不是人们的共识。

Ævar Arnfjörð Bjarmason 建议将默认值改为使用外部 gzip,保留内部实现来作为一个选项,或者在找不到外部程序时作为一个后备方案。这样一来,确保输出内容保持兼容的责任就可以转移到压缩程序上了:任何想确保他们生成的归档文件不被改变的人,都必须确保他们的 gzip 不被改变。由于 Git 开发者并不控制该程序,他们在任何情况下都不能保证其向前兼容。

不过,Carlson 主张尽可能避免保证不变,尤其是隐含的保证:

几年前,我对归档格式做了一个修改,以解决 pax 头文件作为文件提取出来时的权限问题,而 kernel.org 正依赖这个功能,并且被破坏了。Linus 因此而对我大吼大叫。

从那时起,我就非常反对我们在没有明确规定的情况下保证输出格式的一致性。我以前发过一些 patch,但我记得没有被采纳,这些 patch 明确地记录了这一点。我非常不希望人们依赖我们的当前行为,除非我们明确保证。

他继续建议说,Git 可以保证未压缩的归档格式的稳定性。不过这种格式必须是版本化的,因为 SHA-256 的过渡如果发生的话,无论如何都会迫使这种格式发生变化(Bjarmason 对这种说法表示质疑)。carlson 总结说,总的来说,对于任何希望结果不变的人来说,在检查校验和之前先解压存档文件,很可能会是一个必要动作了。他后来重申,在他看来,实现一个稳定的 tar 格式是可行的,但增加压缩就不可行了。"我个人觉得这太难了,不打算在这方面下功夫了"。

Konstantin Ryabitsev 说,虽然他理解 carlson 想要避免承诺输出格式的这个愿望,"我也认为这是那些尽管你尽力防止发生,也还是会发生的事情之一"。他建议在 git archive 中加入一个保证不改变的 –stable 选项。

What next?

截至本文撰写的时候,Git 社区还没有决定是否要因为这一事件而做出什么改变。Bjarmason 认为,Git 社区应该满足其用户的需求,即使他们开始依赖一个从未宣传过的稳定功能:

很不幸的,这些人也许不应该这么做,但这已经自然而然地发生了。我认为在这个时候随意改变输出内容是不负责任的,特别是当它似乎很容易找到一些大家都会满意的折衷方案时。

他后来发布了一个 patch set,回退到了以前的行为,但也添加了说明指出这种行为在未来可能会改变。

不过,还是很难确保在这种方面保证不变,可能会很难维护(尤其是在处理别人定义的文件格式时),而且可能会阻碍其他类型的进展。例如,替代 gzip 就可以得到更好的压缩工作,可以更有效地进行压缩;如果不能把当前的算法抛弃掉,就会阻碍 Git 获得这些本可以获得的好处。即使 Git 默认恢复去使用外部 gzip 程序,该程序本身也可能发生变动,也许像 GitHub 这样的 downstream 用户可能决定不再支持这种格式。

因此,如果这个问题再次出现也就不是什么奇怪的事了。Git 项目不愿意在其维护工作中加入稳定性保证,其下游用户也是如此;GitHub 曾说过,在下次产生校验和变动之前,会给出一些预先提醒,但并没有说这种变动不会再发生了。build 系统的开发者和用户可能要重新思考他们对互联网上一个专有服务所使用的特定压缩格式产生依赖是否合理的做法。下一次问题再出现时,他们将不能说他们没有被警告过了。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

4ddaa59ffca2c257bd34621e4f1e1c86.jpeg

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值