Git:当已知源代码发生重大变化时应用补丁的建议

  • 本文关键字:应用 变化 补丁 源代码 Git git patch
  • 更新时间 :
  • 英文 :


大约五个月前,我们开始了一个项目,对遗留的PHP-4/5应用程序进行检修和升级,将其迁移到PHP-7(以及许多其他东西)。这个应用程序由2700多个文件组成,几乎所有的文件都做了大量的修改。

与此同时,遗留应用程序继续支持客户,到目前为止已经进行了大约250次更改。我有(也能做……)git补丁来表示这些变化。我的直接问题是,他们中的大多数不git apply

当然,很容易理解为什么:"行号",如补丁中所表达的,几乎是无用的。尽管在大多数情况下,查找的源代码在那里,但它可能已经移动了一段距离。

我目前的想法(基于对大约30个补丁文件的检查)是,在有用的情况下,要打补丁的文字源代码仍然是,逐字逐句地存在于源文件中,只是不在预期的位置。

虽然我足够现实,知道许多这些补丁将不得不分析和手工制作,我想尽量减少这一点,既为了时间又为了准确性。我希望那些将要做这件事的人……包括我在内……为了能够尽可能地利用自动化工具,知道他们必须检查每个补丁的工作。我不幻想我有可能一次自动处理所有这些文件,"Shazam."

那么,谁遇到过类似的情况呢?你建议我怎么做?一个建议是使用patch命令和fuzz选项,注意,这可能会起作用可能会导致应用不正确的补丁。

(我们计划在任何情况下一次做一个补丁:"patch, git commit, rinse and repeat。"这样我们就可以git diff检查每个更改的完整性。

请求"战争故事"。谢谢。

git apply提供了几个可用于启发式或半手动应用补丁的选项,其中大多数在git-apply(1)手册页中有描述:

  • -C可以减少必须在块中匹配才能成功打补丁的上下文行数。

    -C<n>
    确保每次更改前后至少<n>行周围上下文匹配。当周围的上下文行较少时,它们必须全部匹配。默认情况下,没有上下文被忽略。
  • --recount将忽略行号。

    --recount
    不要相信块头中的行数,而是通过检查补丁来推断它们(例如在编辑补丁后没有适当地调整块头)
  • --reject将在.rej文件中留下无法应用的大块,就像patch一样。然后,您可以检查这些文件并手动应用更改。

    --reject
    对于原子性,git apply默认会使整个补丁失败,并且在某些块不适用时不触及工作树。此选项使它应用补丁中适用的部分,并将被拒绝的块留在相应的*中。rej文件。
  • --3way将尝试三向合并,假设补丁最初是由git生成的。

    -3
    --3way
    当补丁不能干净地应用时,如果补丁记录了它应该应用的blobs的身份,并且我们在本地有这些blobs,则退回到3-way合并,可能会在工作树中的文件中留下冲突标记供用户解决。该选项暗示--index选项,与--reject--cached选项不兼容

就我个人而言,我已经使用git apply -C1 --recount成功地将被子补丁转换为git提交。

或者,您可以简单地使用patch实用程序来应用补丁,而根本不使用git apply命令。默认情况下,patch将模糊地应用块,并在.rej文件中留下完全无法应用的块;如果给出了--merge选项,则失败的块将生成冲突标记。

我也有类似的经历。我们的团队正在开发不同芯片组和不同版本的谷歌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

不同的补丁和前后的补丁和列表然后被交付给团队成员。如果git diff补丁不能自动应用,我们就按照前后补丁手动应用它。虽然工作量很大,但一定要完成。

相关内容

最新更新