如何将git补丁从一个存储库应用到另一个存储库?

时间:2009-05-31 11:32:38

标签: git patch git-submodules git-patch

我有两个存储库,一个是库的主要仓库,另一个是使用该库的项目。

如果我修复了subservient项目,我想要一个简单的方法将该补丁应用到上游。

每个存储库中文件的位置不同。

  • 主要回购: www.playdar.org/static/playdar.js
  • 项目: playlick.com/lib/playdar.js

我尝试在playlick项目中使用git format-patch -- lib/playdar.js,然后在主playdar repo上使用git am,但补丁文件中的不同文件位置引发了错误。

是否有一种简单的方法可以将给定文件中给定提交的补丁应用到其他地方的另一个任意文件中?

对于奖励积分,如果您要应用补丁的文件不在git存储库中该怎么办?

8 个答案:

答案 0 :(得分:96)

如果手动编辑补丁文件是不可能的或不可行的,可以使用标准选项(git applygit format-patch和GNU patch中提供)来完成。

  1. -p<n>从补丁中的路径中删除n个前导目录。

  2. 处理-p后,--directory=<root>会在应用之前将root添加到修补程序中的每个路径。

  3. 实施例

    因此,对于您的示例,要获取最初位于static/playdar.js并将其应用于lib/playdar.js的修补程序,您将运行:

    $ cat patch_file | git am     \ 
              -p1                 \ # remove 1 leading directory ('static/')
             --directory='lib/'     # prepend 'lib/'
    

答案 1 :(得分:35)

git format-patch生成的补丁只是一个文本文件 - 您可以编辑差异标题,以便修改不同的路径。

所以例如它会产生这样的东西:

diff --git a/lib/playdar.js b/lib/playdar.js
index 1234567..89abcde
-- a/lib/playdar.js
++ b/lib/playdar.js

您所要做的就是将lib/playdar.js更改为static/playdar.js,然后通过git am"

运行补丁

标准GNU补丁实用程序应该可以为那些没有git ---但没有使用format-patch {{1}运行-M的人阅读补丁在这种情况下产生重命名补丁的选项,因为对它们的支持不是通用的。

答案 2 :(得分:4)

假设两个项目都是git项目,听起来submodules将是最适合你的。这允许git项目动态链接到另一个git项目,实际上是在另一个git仓库中烘焙git repo,两者都有自己独特的生命。

换句话说,将“main repo”添加为“project”中的子模块。每当你在“主回购”中提交/推送新内容时,你只需git pull将它们带回“项目”。

答案 3 :(得分:2)

完成Henrik's answer,并获得奖励积分

  

如果要应用补丁的文件不在git存储库中该怎么办?

如果您可以访问来自git存储库的补丁的候选文件目录,您可以先将目录/文件树转换为git存储库本身! ('git init':git存储库毕竟是根目录中的.git。) 然后,您将该repo设置为主项目的子模块。

答案 4 :(得分:1)

您可以添加新遥控器并从中拉出。 Article with details.

$ cd <path-to-repoB>
$ git remote add repoA <git-URL-for-repoA>
$ git pull repoA

答案 5 :(得分:0)

我认为子树是解决问题的最佳解决方案

Tutorial 1

Tuorial 2

答案 6 :(得分:0)

您可以暂时删除(重命名)主存储库。

cd to/main/project
mv .git .git_
cd to/sub/project
git apply patchname
cd -
mv .git_ .git

答案 7 :(得分:0)

使用--relative format-patch选项可以改进抽象(隐藏有关生成补丁的存储库的无关详细信息)。

[repository-with-changes]
git format-patch --relative=(path-to-library) (base-commit-for-patch) ## 'HEAD~1'

我发现在应用补丁时需要--3way选项(以避免does not exist in index错误) - 您的里程可能会有所不同。如果您的目标路径不是存储库的根目录,则可能只需要使用--directory=(...)

[repository-to-update]
git am --3way --directory=(path-to-library) (patch-file)
  • format-patch将在每次提交时为“base”创建一个补丁文件。

  • --relative选项的文档似乎是missing in some cases,但无论如何它似乎都有效(从2.7.4版开始)。