【问题标题】:Creating a patch file from a diff of 2 folders从 2 个文件夹的差异创建补丁文件
【发布时间】:2026-02-13 20:35:01
【问题描述】:

我对一个开源项目进行了一些更改,但没有花时间创建正确的补丁文件。

现在,项目的维护者发布了一个新版本,在新的和编辑的文件中,有一堆重命名的文件。

将更改应用到新版本的最佳方式是什么?
我对 diff/patch 的使用完全陌生,如果我能用 git 完成它,那就更好了。

【问题讨论】:

  • 你使用git clone创建本地仓库了吗?
  • 不幸的是,原始源不在 git 下,它在每个新版本的包中发布。但我使用 git 作为我的版本。

标签: git diff patch


【解决方案1】:

如果您有两个相似的目录ab,并且您希望ba 相同,您可以创建并应用补丁:

$ diff -ur b a > ba.diff
$ patch -i ba.diff

假设您有目录local(包含您的本地版本的 upstream1.0)、upstream1.0upstream1.1。创建并将您的更改应用到upstream1.1

$ diff -ur upstream1.0 local > my.diff
$ cd upstream1.1
$ patch -i ../my.diff 

检查文档中的补丁,并尝试说服上游维护者使用 git。如果您可以使用 git 工具来处理本地存储库,事情会简单得多。

【讨论】:

  • diff -urN b a > ba.diff 如果您在 a 中创建了不在 b 中的新文件
  • diff -uarN b a > ba.diff 如果某处存在二进制文件会更好。
  • 我会写成 -uraN 因为快捷方式更容易记住 :)
  • 我发现出于某种原因有必要 cd 进入目录并运行patch -p1 < ../my.diffaskubuntu.com/questions/975879/…
【解决方案2】:

如果项目在 git 下并且您尚未在本地提交更改,您可以简单地执行 git diff > file.patch 以获取可修补的差异数据。如果您已在本地提交更改,您可以通过git log 找到您之前的提交,而不是git diff commit_string > file.patch

如果项目不在 git 下,或者如果你 d/l source 没有克隆存储库(如标题所示),你可以使用 diff -urN original_dir new_dir > file.patch 创建补丁文件。在这两种情况下,您都可以稍后尝试使用补丁来应用补丁。

但是,请考虑使用 git 工具将您的更改与新版本合并,因为 git 也能够跟踪文件名更改。您需要大量了解 git 本身,并且需要一些时间才能正确使用它 - 您可能应该在开始使用它之前备份您的工作。

【讨论】:

    【解决方案3】:

    Git 支持检测文件重命名,所以如果你幸运的话,它会帮助你。以下是您应该做的大致草稿。

    导入原版:

    tar zxvf open-source-project-0.1.tar.gz 
    mv open-source-project-0.1 open-source-project
    cd open-source-project
    git init
    git add .
    git commit -m "Initial checkin of open-source-project-0.1"
    git tag open-source-project-0.1
    

    现在您可以在单独的分支中应用您的原始更改:

    git checkout -b mychanges
    cp /somewhere/where/your/changes/files/are/* .
    git diff
    git add .
    git commit -m "My changes"
    git tag my_changes_001
    

    然后你更新到较新的版本:

    git checkout master
    tar zxvf open-source-project-0.2.tar.gz 
    mv open-source-project-0.2/* .
    rmdir open-source-project-0.2
    git add .
    git commit -m "Update to open-source-project-0.2"
    git tag open-source-project-0.2
    

    到目前为止,所有内容都已签入 git 存储库,现在是开始尝试合并更改的时候了:

    git checkout -b merge_test open-source-project-0.2
    git pull . my_changes_001
    

    祝你好运……

    如果你想手动合并文件,我真的推荐使用KDiff3。假设 file1.c 来自 open-source-project-0.1,file2.c 来自 open-source-project-0.2 和 file3.c 来自您的更改,运行

    kdiff3 -o merged_file.c file1.c file2.c file3.c
    

    【讨论】:

      【解决方案4】:

      由于声誉低,我无法发表评论。所以我会添加一个新的答案。我尝试了上面的答案之一仍然存在空白行问题。不过,下面的方法对我有用。

      diff -uraBN upstream local > filename.patch
      cd upstream
      patch --dry-run -p1 -i filename.patch #highly recommended recommended
      patch -p1 -i filename.patch
      

      【讨论】:

        【解决方案5】:

        您可以尝试以前在这里向我提出的建议,一个有趣的“差异化”解决方案:首先克隆项目的最新版本。它不应该有任何本地更改。确保 .git 文件夹在那里。然后将您的工作树(即除 .git 文件夹之外的所有文件)复制到克隆的存储库中。现在,如果您键入“git st”,您将看到所有已更改的内容。如果 git st 报告的文件实际上没有更改,您还需要整理间距和行尾 (git config core.autocrlf ...)。

        现在对于 git st list 中的每个文件,如果您键入 git diff,您将看到您所做的更改。

        然后我会一个一个地编辑文件,直到 git st 看起来像我想要提交的。

        我不会依赖制作补丁,因为它们非常挑剔。您很可能会收到“无法应用补丁”,而上面的解决方案为您提供了一个未暂存的更改列表,您可以按照您想要的任何顺序进行处理。

        【讨论】:

          【解决方案6】:

          您可能应该查看git rebase。也许即使是简单的git pull 也能满足您的需求。

          【讨论】:

            最近更新 更多