如何将 git 补丁从一个存储库应用到另一个存储库?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/931882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to apply a git patch from one repository to another?
提问by James Wheare
I have two repositories, one is the main repo for a library, and the other is a project using that library.
我有两个存储库,一个是库的主要存储库,另一个是使用该库的项目。
If I make a fix to the in the subservient project, I'd like an easy way to apply that patch back upstream.
如果我修复了从属项目中的 ,我想要一种简单的方法来将该补丁应用回上游。
The file's location is different in each repository.
每个存储库中的文件位置都不同。
- Main repo:
www.playdar.org/static/playdar.js
- Project:
playlick.com/lib/playdar.js
- 主要回购:
www.playdar.org/static/playdar.js
- 项目:
playlick.com/lib/playdar.js
I tried using git format-patch -- lib/playdar.js
on the playlick project, and then git am
on the main playdar repo, but the differing file locations in the patch file raised an error.
我尝试git format-patch -- lib/playdar.js
在 playlick 项目上使用,然后git am
在主 playdar 存储库上使用,但补丁文件中不同的文件位置引发了错误。
Is there an easy way to apply the patch from a given commit on a given file to another arbitrary file elsewhere?
有没有一种简单的方法可以将给定文件上给定提交的补丁应用到其他地方的另一个任意文件?
For bonus points, what if the file you want to apply the patch to isn't in a git repository?
对于奖励积分,如果您要应用补丁的文件不在 git 存储库中怎么办?
回答by vergenzt
If manually editing the patch file is out of the question or infeasible, this can be done with standard options (available in git apply
, git format-patch
and GNU patch
).
如果手动编辑补丁文件是问题或不可行的了,这可以用标准的选项(可以在做git apply
,git format-patch
和GNU patch
)。
-p<n>
removesn
leading directories from the paths in the patch.After processing
-p
,--directory=<root>
prependsroot
to each of the paths in the patch before applying.
-p<n>
n
从补丁中的路径中删除前导目录。处理之后
-p
,--directory=<root>
预先考虑root
到各贴剂中的路径的应用之前。
Example
例子
So, for your example, to take a patch that was originally on static/playdar.js
and apply it to lib/playdar.js
, you would run:
因此,对于您的示例,要获取最初打开的补丁static/playdar.js
并将其应用于lib/playdar.js
,您将运行:
$ cat patch_file | git am \
-p1 \ # remove 1 leading directory ('static/')
--directory='lib/' # prepend 'lib/'
回答by araqnid
The patch produced by git format-patch
is simply a text file-- you can edit the diff headers so that it modifies a different path.
生成的补丁git format-patch
只是一个文本文件——您可以编辑差异标头,以便它修改不同的路径。
So for instance it would have produced something like this:
因此,例如它会产生这样的东西:
diff --git a/lib/playdar.js b/lib/playdar.js
index 1234567..89abcde
-- a/lib/playdar.js
++ b/lib/playdar.js
All you have to do is change lib/playdar.js
to static/playdar.js
and then run the patch through git am"
所有你需要做的是改变lib/playdar.js
对static/playdar.js
,然后通过运行该补丁git am"
The patch should be readable by the standard GNU patch utility for people who don't have git
--- but don't run format-patch
with the -M
, -C
etc. options to produce rename patches in that case, because the support for them isn't universal.
这个补丁应该是标准的GNU补丁程序为没有谁的人可读git
---但不运行format-patch
与-M
,-C
等选项,在这种情况下产生的重命名的补丁,因为对他们的支持是不具有普遍性。
回答by Henrik Paul
Assuming both projects are git projects, it sounds like that submoduleswould be the perfect fit for you. This allows a git project dynamically link to another git project, essentially baking a git repo right inside another git repo, both having their own distinct lives.
假设这两个项目都是 git 项目,听起来子模块将非常适合您。这允许一个 git 项目动态链接到另一个 git 项目,本质上是在另一个 git 仓库中烘焙一个 git 仓库,两者都有自己独特的生活。
In other words, add "main repo" as a submodule in "project". Whenever you commit/push new stuff in "main repo", you just git pull
them back into "project".
换句话说,在“project”中添加“main repo”作为子模块。每当您在“主存储库”中提交/推送新内容时,您只需将git pull
它们放回到“项目”中。
回答by VonC
To complete Henrik's answer, and to go for the bonus point
完成Henrik 的回答,并获得奖励积分
what if the file you want to apply the patch to isn't in a git repository?
如果要应用补丁的文件不在 git 存储库中怎么办?
If you have access to the directories of the file candidate for a patch coming from a git repository, you could first transform that tree of directories/files into a git repository itself! ('git init
': a git repository is just a .git within a root directory after all).
Then you would set that repo as a submodule for your main project.
如果您可以访问来自 git 存储库的补丁的候选文件的目录,您可以首先将该目录/文件树转换为 git 存储库本身!(' git init
':git 存储库毕竟只是根目录中的一个 .git)。
然后,您可以将该存储库设置为主项目的子模块。
回答by nobar
Using the --relative
option to format-patch
can improve the abstraction (hide irrelevant details about the repository from which the patch was generated).
使用--relative
选项format-patch
可以改进抽象(隐藏关于生成补丁的存储库的无关细节)。
[repository-with-changes]
git format-patch --relative=(path-to-library) (base-commit-for-patch) ## 'HEAD~1'
I have found the --3way
option to be required when applying the patch (to avoid does not exist in index
error) -- your mileage may vary. Using --directory=(...)
is likely only necessary if your target path is not the root of the repository.
我发现--3way
应用补丁时需要的选项(以避免does not exist in index
错误) - 您的里程可能会有所不同。--directory=(...)
仅当您的目标路径不是存储库的根目录时,才可能需要使用。
[repository-to-update]
git am --3way --directory=(path-to-library) (patch-file)
format-patch
will create one patch file per commit to the current branch since 'base'.The documentation for the
--relative
option seems to be missing in some cases, but it appears to work anyway (as of version 2.7.4).
回答by Der_Meister
You can add a new remote and pull from it. Article with details.
您可以添加一个新的遥控器并从中拉出。文章详细。
$ cd <path-to-repoB>
$ git remote add repoA <git-URL-for-repoA>
$ git pull repoA
回答by Mauro
I think subtree is the best solution for your problem
我认为 subtree 是您问题的最佳解决方案
回答by ya.teck
You can just remove (rename) temporarily the main repository.
您可以暂时删除(重命名)主存储库。
cd to/main/project
mv .git .git_
cd to/sub/project
git apply patchname
cd -
mv .git_ .git