Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Git 跨具有不同提交历史记录的存储库应用修补程序_Git_Diff_Patch - Fatal编程技术网

Git 跨具有不同提交历史记录的存储库应用修补程序

Git 跨具有不同提交历史记录的存储库应用修补程序,git,diff,patch,Git,Diff,Patch,假设我有两个相似但不同的提交历史的存储库A和B 一个例子可能是两个PythonFlask应用程序,或者两个RubyonRails应用程序,它们共享许多相似的文件,但并不完全相同 我在存储库a上做了一个更改,我也希望将其应用于存储库B。在将其应用于存储库B时可能会有一些冲突,但没关系,我希望看到它们是什么,并解决它们 我尝试了以下方法从repo A生成补丁 > cd ~/git/repoA/ > git format-patch HEAD~ 0001-My-Example-Commit

假设我有两个相似但不同的提交历史的存储库A和B

一个例子可能是两个PythonFlask应用程序,或者两个RubyonRails应用程序,它们共享许多相似的文件,但并不完全相同

我在存储库a上做了一个更改,我也希望将其应用于存储库B。在将其应用于存储库B时可能会有一些冲突,但没关系,我希望看到它们是什么,并解决它们

我尝试了以下方法从repo A生成补丁

> cd ~/git/repoA/
> git format-patch HEAD~
0001-My-Example-Commit.patch
> mv 0001-My-Example-Commit.patch ~/git/repoB
然后我试着将补丁应用到回购协议B中

> cd ~/git/repoB
> git am 0001-My-Example-Commit.patch
Applying: My Example Commit
error: patch failed: Gemfile:20
error: Gemfile: patch does not apply
error: patch failed: Gemfile.lock:125
error: Gemfile.lock: patch does not apply
error: patch failed: app/assets/stylesheets/application.scss:29
error: app/assets/stylesheets/application.scss: patch does not apply
....
....
error: patch failed: spec/views/application/_mobile_navigation.html.erb_spec.rb:44
error: spec/views/application/_mobile_navigation.html.erb_spec.rb: patch does not apply
Patch failed at 0001 Using Devise for authentication
hint: Use 'git am --show-current-patch' to see the failed patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
如图所示,它会导致多个错误/冲突。很好,我将尝试查看冲突并修复它们,就像我在常规合并中所做的那样:

git status
On branch test-git-apply
You are in the middle of an am session.
  (fix conflicts and then run "git am --continue")
  (use "git am --skip" to skip this patch)
  (use "git am --abort" to restore the original branch)

nothing to commit, working tree clean
Git甚至没有将更改作为差异应用,因此没有差异/修改的文件,我甚至看不到冲突是什么,也无法尝试修复它们

有没有办法强制git显示冲突?

谢谢

编辑

我知道
--directory
选项存在,但我认为它不适用于这里,因为我的补丁文件已经相对于同一根生成。例如

diff --git a/Gemfile b/Gemfile
index c970c34..ffc812d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -20,12 +20,17 @@ gem "webpacker", "~> 3.5", ">= 3.5.5"
 #
 gem "bcrypt", "~> 3.1", ">= 3.1.10"
 gem "cancancan", "~> 3.0"
....
没有冲突。1修补程序无法应用。例如,补丁可能会说:第87行显示“foo”。在随后的第88行中,将“bar”更改为“baz”。第89行为“quux”。但是您的第87到89行没有读“foo”、“bar”和“qux”,并且附近也没有包含该序列的行。这取决于你,程序员,如何处理补丁

所以,使用它。阅读补丁。检查您的文件并决定如何处理此修补程序


1此处不能有冲突,因为修补程序本身并不表示对同一行的两组不同更改。当您有两个差异时,就会发生冲突:一个说在第88行将bar更改为baz(这是可能的),另一个说在第88行将bar更改为rab(这也是可能的)。这两个变化相互冲突

一个补丁只提供一个改变。它要么适用,要么不适用


修补的替代方案 这里有两种选择。从低效到高效的顺序:

  • 确保来自repo A的修补程序是由
    git格式的修补程序--full index
    生成的。使用
    git-am
    时,请使用
    git-am-3
    (或将
    am.threeWay
    配置为
    true
    )。这样,
    A
    上的diff将包含文件父版本的完整blob散列。如果父文件版本的blob在repob中可用,Git将能够使用blob散列和补丁来重建真正合并所需的三个输入:公共基本版本和从基本版本修改的两个输入

  • 或者,在repo B中使用
    git remote add
    添加对repo A的直接访问。选择一个远程名称,该名称将在以后提醒您这是为了什么(或者在之后立即删除远程)。然后使用此远程名称运行
    git fetch
    ,将来自repo A的提交带到repo B中,以便所有提交在B中本地可用。现在,您可以运行以下命令,而不是
    git format patch
    git am

    git cherry-pick <hash>
    
    提供显示在存储库中的哈希ID。如果您还没有hash ID,那么执行git fetch实际上会获取具有该hash ID的blob,这样就不需要单纯的希望了。

    注意,您会看到:

    hint: Use 'git am --show-current-patch' to see the failed patch
    
    但是,正如Git2.25(2020年第1季度)中所记录的那样,这并不完全正确

    参见(2019年10月23日)作者 (于2019年11月10日合并)

    am--显示当前修补程序
    提供完整的电子邮件消息 现有的措辞给人的印象是,它只给出了
    $GIT_DIR/rebase apply/patch
    文件的内容,即补丁本身,,但该选项实际上会发出正在处理的整个电子邮件(iow,来自“GIT mailspilt”的一个输出文件)


    因此,您可能必须从该电子邮件中提取导致冲突的确切部分。

    我理解您的意思,但在您的示例中,git仍然无法尝试对第87-89行进行这些更改,而只是强制与已有内容发生冲突,这似乎有些奇怪(使用
    >>>
    的问题是,要构建一个适当的冲突,Git必须找到第三个文件,即要修补的两个文件都发生更改的共同祖先,以及要应用的修补程序发生更改的共同祖先。也就是说,要应用的修补程序说“对第87-89行进行此更改”例如,Git需要找到包含这些行的文件,如第87-89行,以便找到文件中对应的行。Git可以对一些Git修补程序执行此操作,因为它们的
    索引
    行:
    索引
    行包含原始文件的哈希ID。如果修补程序包含
    索引
    行,则原始文件(作为存储库中存储的blob),您使用
    git apply--3way
    git am--3way
    ,git将尝试此操作。如果您使用
    git format patch
    生成补丁,它们将具有索引行(并且您可以使用
    --full index
    来防止可能使其模棱两可的缩写),但这些可能与存储库中的实际blob不对应。请注意,如果您可以直接访问repo A并希望选择一些提交从它到不相关的repo B,您可以
    git fetch
    A的提交到repo B,然后在repo B中运行
    git cherry pick
    。此策略将进行三方合并,并提供您想要的冲突线。非常感谢您的更新和详细的提纲。这一解释非常有意义,并且可以添加另一个
    remote
    和执行
    git fetch
    合并更改正是我所需要的。
    git diff <parent of hash> <hash>   # what they changed
    
    git diff <parent of hash> HEAD     # what we changed
    
    index a1539a7ce682f10a5aff3d1fee4e86530e058c89..98f88a28d3227c436ecf1765f75b7f4e8e336834 100755
    
    hint: Use 'git am --show-current-patch' to see the failed patch