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

发布于 2024-07-23 20:59:30 字数 524 浏览 15 评论 0原文

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

如果我在从属项目中进行修复,我想要一种简单的方法来将该补丁应用回上游。

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

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

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

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

为了加分,如果您要应用补丁的文件不在 git 存储库中怎么办?

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

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.

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

堇色安年 2024-07-30 20:59:30

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

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

  2. 处理 -p 后,--directory= 在应用之前将 root 附加到补丁中的每个路径。

因此,对于您的示例

,要获取最初位于 static/playdar.js 上的补丁并将其应用到 lib/playdar.js,您将运行:

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

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).

  1. -p<n> removes n leading directories from the paths in the patch.

  2. After processing -p, --directory=<root> prepends root to each of the paths in the patch before applying.

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:

$ cat patch_file | git am     \ 
          -p1                 \ # remove 1 leading directory ('static/')
         --directory='lib/'     # prepend 'lib/'
毁梦 2024-07-30 20:59:30

由 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,然后通过 < code>git am"

对于没有 git 的人来说,标准 GNU 补丁实用程序应该可以读取该补丁——但不运行 format-patch< /code> 与 -M-C 等选项在这种情况下生成重命名补丁,因为对它们的支持并不通用。

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.

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"

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.

平定天下 2024-07-30 20:59:30

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

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

我发现应用补丁时需要使用--3way选项(以避免索引中不存在错误)——您的情况可能会有所不同。 仅当您的目标路径不是存储库的根目录时才需要使用 --directory=(...)

[repository-to-update]
git am --3way --directory=(path-to-library) (patch-file)

  • format-patch 将从“base”开始每次提交到当前分支创建一个补丁文件。

  • --relative 选项的文档似乎在某些情况下丢失,但它似乎无论如何都可以工作(从版本 2.7.4 开始)。

Using the --relative option to format-patch can improve the abstraction (hide irrelevant details about the repository from which the patch was generated).

[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.

[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).

小霸王臭丫头 2024-07-30 20:59:30

假设这两个项目都是 git 项目,听起来 子模块 将非常适合你。 这允许一个 git 项目动态链接到另一个 git 项目,本质上是在另一个 git 存储库中烘焙一个 git 存储库,两者都有自己独特的生命周期。

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

Assuming both projects are git projects, it sounds like that submodules would 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.

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".

萌能量女王 2024-07-30 20:59:30

完成Henrik的回答,并获取奖励积分

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

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

To complete Henrik's answer, and to go for the bonus point

what if the file you want to apply the patch to isn't in a git repository?

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.

缺⑴份安定 2024-07-30 20:59:30

您可以添加一个新的遥控器并从中拉出。 包含详细信息的文章。

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

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
勿忘心安 2024-07-30 20:59:30

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

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文