有什么方法可以有效地应用大型git补丁吗



我们收到了一个大补丁,其中修改了大约17000个文件。其大小为5.2G。使用git apply -3贴片时,12小时后仍未完成。

我们将每个文件的补丁分成更小的补丁,并逐一应用,这样至少我们可以看到进展。

它又一次被一个文件补丁卡住了,这个补丁仍然有111M那么大。它修改HTML文件。

我们将这个文件补丁分为每个区块的较小补丁,得到了大约57000个区块补丁。每个区块补丁大约需要2-3秒,因此它将比应用文件补丁花费更多的时间。我试着把它分成更多的块。

有什么方法可以有效地应用这么大的补丁吗?谢谢

更新:

正如@ti7所建议的,我尝试了patch,它解决了问题。

就我而言,我们有两种大补丁。

一种是添加/删除一个大二进制文件,二进制文件的内容以文本形式包含在补丁中。其中一个二进制文件是188M,删除它的补丁大小是374M。

另一种是修改一个大的文本,并且有数百万的删除和插入。其中一个文本文件在前面是70M,后面是162M。补丁大小为181M,插入2388623个,缺失426959个。

经过一些测试,我认为;"大";描述了插入和删除的次数。

对于二进制补丁,

  • git-apply-3,7秒
  • git应用,6秒
  • 补丁,5秒

对于文本补丁,

  • git-apply-3,卡住,10分钟后未完成
  • git应用,卡住,10分钟后未完成
  • 补丁,3秒

二进制文件只有1个插入和/或1个删除。CCD_ 3或CCD_。所有都可以接受。

文本中插入和删除的内容太多。显然,patch在这种情况下要好得多。我读了一些关于patch的帖子,发现patch的某些版本无法添加/删除/重命名文件。幸运的是,我机器上的patch运行良好。

因此,我们将一体式修补程序拆分为每个文件的较小修补程序。我们先尝试timeout 10s git apply -3 file_patch。如果无法在10秒内完成,请尝试timeout 10s patch -p1 < file_patch

最后,花了大约1个半小时才将17000块贴片全部贴上。这比使用一体式贴片然后无所事事地被卡住12个小时要好得多。

我也试过patch -p1 < all_in_one_patch。只花了1米27秒。因此,我认为我们可以进一步改进补丁流。

您可以使用patch(维基百科)而不是git apply来加快修补速度!

据我所知,patch直接逐行弹出一个新文件,边写边拼接更改,而git apply则进行额外的上下文检查(正如评论中的@j6t所述,尽管我还没有确认,但会尝试在写出整个文件之前立即加载并修补它)

patch的另一个参数:git apply现在正式限制为1GB。

Git 2.39(2022年第四季度);CCD_ 18">(man)将其输入限制为小于1GiB的比特。

参见Taylor Blau(ttaylorr)提交的f1c0e39(2022年10月25日)
(由Taylor Blau-ttaylorr-在提交c41ec63时合并,2022年10月30日)

apply:拒绝大于~1 GiB的补丁

报告人:정재우
建议人:Johannes Schindelin

应用程序代码不准备处理超大文件
它使用"CCD_ 22";在一些地方;CCD_ 23";在其他方面。

当在两种类型之间切换时,这种组合会导致不幸的问题
使用"CCD_ 24";阻止我们处理大文件,因为大的偏移量会缠绕并溢出到小的负值中,这可能会导致错误的行为(例如使用负偏移量访问补丁缓冲区)。

从";CCD_ 25";至";CCD_ 26";即使在LLP64平台上也存在截断问题;CCD_ 27";与";CCD_ 28";,因为前者是无符号的,但后者不是。

为了避免git apply(man)中潜在的溢出和截断问题,应用与dcd1742中类似的处理("git apply0:拒绝大于~1GB的文件",2015-09-24,Git v2.7.0-rc0-第2批中列出的merge),其中xdiff代码被教导以类似的原因拒绝大文件。

最大大小的选择有些随意,但选择一个不到千兆字节的值可以使它翻倍,而不会溢出2^31-1(在此之后,我们的值将变为负数)
为了给自己一点额外的余量,最大补丁大小是MiB,比完整的GiB小,这给了我们一些斜率,以防我们分配"CCD_ 32";或类似的。

幸运的是,这些转换问题的安全含义相对来说并不令人感兴趣,因为需要说服受害者应用恶意补丁。


Gabriel Devillers在评论中指出:

我试图用Git 1.41应用1.6 GB大小的补丁,但得到了错误:

git apply: failed to read: No such file or directory 

这是完全不清楚的。


使用Git 2.42(2023年第3季度);CCD_ 33">(man)当它被馈送过大的补丁输入时踢;它在发生错误时给出的错误信息已得到澄清。

参见Phillip Wood(phillipwood)提交的42612e1(2023年6月26日)
(由Junio C Hamano合并--gitster-提交84b889b,2023年7月6日)

apply:改进读取补丁时的错误消息

报告人:Premek Vysoky
签字人:Phillip Wood

Commit f1c0e39("apply:拒绝大于~1 GiB的修补程序",2022-10-25,Git v2.39.0-rc0——第9批中列出的合并)增加了对应用程序将处理的修补程序大小的限制,以避免整数溢出
当我们无法读取修补程序时,实现会重新使用现有的错误消息
这是不幸的,因为(a)它没有向用户发出信号,表明补丁太大而被拒绝;(b)它使用error_errno()而没有设置errno。

此修补程序会为修补程序过大的情况添加特定的错误消息
它还更新现有消息,使其更清楚地表明是补丁而不是任何其他文件无法读取,并标记这两条消息进行翻译
;CCD_ 39">(man)前缀也被删除以匹配patch0中的大多数剩余错误消息(仍有一些以"git apply"为前缀的错误消息,并且在该补丁之后没有被标记为翻译)
f1c0e39中添加的测试将相应更新。

最新更新