代码之家  ›  专栏  ›  技术社区  ›  James Wheare

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

  •  66
  • James Wheare  · 技术社区  · 16 年前

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

    如果我修复了在从属项目中的,我希望有一个简单的方法将补丁应用到上游。

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

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

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

    有没有一种简单的方法可以将补丁从给定文件的给定提交应用到其他任意文件?

    对于奖励点,如果要应用修补程序的文件不在Git存储库中怎么办?

    8 回复  |  直到 7 年前
        1
  •  90
  •   vergenzt    11 年前

    如果手动编辑补丁文件不存在问题或不可行,可以使用标准选项(在 git apply , git format-patch 和GNU patch )

    1. -p<n> 移除 n 从补丁中的路径引导目录。

    2. 处理后 -p , --directory=<root> 预置 root 在应用之前,对修补程序中的每个路径。

    例子

    因此,以您的示例为例,使用最初在 static/playdar.js 并将其应用于 lib/playdar.js ,您将运行:

    $ cat patch_file | git am     \ 
              -p1                 \ # remove 1 leading directory ('static/')
             --directory='lib/'     # prepend 'lib/'
    
        2
  •  36
  •   0 _ Edward Ned Harvey    7 年前

    补丁由 git format-patch 只是一个文本文件——您可以编辑diff头文件,以便它修改不同的路径。

    例如,它会产生这样的结果:

    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 -M , -C 在这种情况下产生重命名补丁的选项,因为对它们的支持不是通用的。

        3
  •  4
  •   Henrik Paul    16 年前

    假设这两个项目都是Git项目,听起来是这样的 submodules 非常适合你。这允许一个git项目动态链接到另一个git项目,本质上是在另一个git repo内部烘焙一个git repo,两者都有自己独特的生命。

    换句话说,在“项目”中添加“主回购”作为子模块。每当你在“主要回购”中承诺/推动新的东西时,你只是 git pull 他们回到“项目”中。

        4
  •  2
  •   Community CDub    8 年前

    完成 Henrik's answer 去拿奖金

    如果要应用修补程序的文件不在Git存储库中怎么办?

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

        5
  •  1
  •   Der_Meister    10 年前

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

    $ cd <path-to-repoB>
    $ git remote add repoA <git-URL-for-repoA>
    $ git pull repoA
    
        6
  •  0
  •   Mauro    10 年前

    我认为子树是解决你问题的最好方法

    Tutorial 1

    Tuorial 2

        7
  •  0
  •   ya.teck    10 年前

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

    cd to/main/project
    mv .git .git_
    cd to/sub/project
    git apply patchname
    cd -
    mv .git_ .git
    
        8
  •  0
  •   Brent Bradburn    7 年前

    使用 --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)
    

    • 格式化补丁 将在每次提交到当前分支时创建一个修补程序文件,从'base'开始。

    • 文件 --相对 选择似乎是 missing in some cases ,但它似乎仍然有效(从2.7.4版开始)。

    推荐文章