大约五个月前,我们开始了一个项目,对遗留的 PHP-4/5 应用程序进行大修和升级,将其迁移到 PHP-7(以及许多其他内容)。此应用程序包含 2,700 多个文件,并且几乎对所有文件都进行了大量更改。
同时,遗留应用程序继续支持客户,到目前为止已经进行了大约 250 次更改。我有(并且可以制作……)git补丁来表示这些更改。我眼前的问题是他们中的大多数都没有git apply。
当然,很容易理解为什么:补丁中表示的“行号”几乎没有用。虽然在大多数情况下,被寻找的源代码是存在,它可能已被移动一段距离。
我现在的想法(根据有关补丁文件的30考试)是,在用地,很多情况下,文字的源代码将被打补丁是仍然存在,逐字,在源文件中,只是没有在预期的地方.
尽管我很现实,知道其中许多补丁必须手动分析和制作,但为了时间和准确性,我想尽量减少这种情况。我希望将要这样做的人......包括我(!)......能够尽可能地利用自动化工具,知道他们将不得不检查每个补丁的工作。我不幻想我可以一次自动完成所有这些文件,“Shazam。 ”
那么,有谁遇到过类似的情况呢?你建议我做什么?一个建议是使用patch带有fuzz选项的命令,请注意,该命令可能会起作用或可能导致应用不正确的补丁。
(我们计划在任何情况下一次做一个补丁:“补丁git commit、冲洗和重复。” 这样我们就git diff可以检查每个更改的完整性。)
“战争故事”要求。谢谢。
git apply提供了几个可用于启发式或半手动应用补丁的选项,其中大部分在 git-apply(1)手册页上进行了描述:
-C可以减少块中必须匹配才能成功修补的上下文行数。
-C<n><n>确保每次更改之前和之后至少有周围上下文的行匹配。当周围上下文的行数较少时,它们都必须匹配。默认情况下,不会忽略任何上下文。
--recount将忽略行号。
--recount- 不要相信块头中的行数,而是通过检查补丁来推断它们(例如,在编辑补丁后没有适当调整块头)。
--reject会留下无法在.rej文件中申请的帅哥,就像patch那样。然后,您可以检查这些文件并手动应用更改。
--reject- 对于原子性,
git apply默认情况下,整个补丁都会失败,并且当某些块不适用时,不会触及工作树。此选项使其应用补丁中适用的部分,并将被拒绝的块保留在相应的 *.rej 文件中。
--3way将尝试三向合并,假设补丁首先是由 git 生成的。
-3--3way- 当补丁不能完全应用时,如果补丁记录了它应该应用的 blob 的标识,并且我们在本地有这些 blob,可能会在工作树的文件中留下冲突标记,则可以使用 3 路合并供用户解决。该选项隐含了
--index选项,并且与--reject和--cached选项不兼容。
就我个人而言,我已经git apply -C1 --recount成功地将 quilt 补丁转换为 git 提交。
或者,您可以简单地使用该patch实用程序来应用补丁,而git apply根本不使用该命令。默认情况下patch会模糊地应用 hunk,并留下完全无法应用到.rej文件中的 hunk;如果--merge给出该选项,失败的帅哥将生成冲突标记。
我也有类似的经历。我们的团队正在研究不同芯片组和不同版本的 Google Android 代码库。所谓的常见问题或功能从一个代码库移植或重用到另一个代码库。
如果是从Android M升级到Android M,那就更容易了。但从 Android L 到 Android M 或 Android N,我们都遇到了问题。有些补丁(通常有数百个)很难直接应用。而且 git 补丁是 ++-- diff,不够清晰或不够直接,当我们必须手动应用它们时,它们会让我们发疯。
该代码库由 400 多个 git 存储库组成。因此,我们为每个存储库创建了按日期排序的提交列表。我们为每次提交制作前后补丁。前后补丁是并排补丁。左边是修改前的文件,右边是修改后的文件。补丁文件夹结构如下<commit>/before:<commit>/after因此,我们可以轻松地使用“Beyond Compare”之类的工具以更友好的方式查看更改。
我们有一个脚本来制作前后补丁。基本上是这样的:
#!/bin/bash
#takes one parameter, the commit
commit=$1
#copy the modified files after the change
git checkout -f $commit
git log -1 $commit --name-only --pretty=%h | tail -n +3 | while read line
do
mkdir -p ~/backup/$commit/after/$(dirname $line)
cp -v $line ~/backup/$commit/after/$line
done
#copy the same files before the change
git checkout -f $commit^
git log -1 $commit --name-only --pretty=%h | tail -n +3 | while read line
do
mkdir -p ~/backup/$commit/before/$(dirname $line)
cp -v $line ~/backup/$commit/before/$line
done
Run Code Online (Sandbox Code Playgroud)
然后,差异补丁以及前后补丁和列表都会交付给团队成员。如果 git diff 补丁无法自动应用,我们只需按照前后补丁手动应用即可。虽然工作量很大,但还是要完成。