【问题标题】:git diff produces incorrect patchgit diff 产生不正确的补丁
【发布时间】:2021-08-24 12:53:23
【问题描述】:

我正在尝试从 git 标签 Amaster 生成补丁,然后将该补丁作为单个提交应用到单独的分支 B(其最后一次提交标记为 A)。

我相信git 在生成补丁时遗漏了一些东西,导致它不能干净地应用。

有问题的文件it/my/application/Something.kt 包含类似于:

package it.my.application

import io.micronaut.runtime.event.annotation.EventListener
import io.micronaut.transaction.annotation.TransactionalEventListener
import io.micronaut.transaction.annotation.TransactionalEventListener.TransactionPhase
import it.my.application.SomethingFacade
import org.slf4j.LoggerFactory
import javax.inject.Singleton

typealias Something = Int

master 中文件重命名为other/my/application/Something.kt 并改为:

package other.my.application

import io.micronaut.runtime.event.annotation.EventListener
import io.micronaut.transaction.annotation.TransactionalEventListener
import io.micronaut.transaction.annotation.TransactionalEventListener.TransactionPhase
import org.slf4j.LoggerFactory
import javax.inject.Singleton
import javax.transaction.Transactional

typealias SomethingId = Int

注意:

  • package it.my.application 行已更改为package other.my.application
  • import it.my.application.SomethingFacade 行已删除
  • 已添加行import javax.transaction.Transactional

查看补丁,这些是git 为这部分代码生成的块:

diff --git a/src/main/kotlin/it/my/application/Something.kt b/src/main/kotlin/other/my/application/Something.kt
similarity index 91%
rename from src/main/kotlin/it/my/application/Something.kt
rename to src/main/kotlin/other/my/application/Something.kt
index ed24736..cb13606 100644
--- a/src/main/kotlin/it/my/application/Something.kt
+++ b/src/main/kotlin/other/my/application/Something.kt
@@ -1,10 +1,11 @@
-package it.my.application
+package other.my.application
 
 import io.micronaut.runtime.event.annotation.EventListener
 import io.micronaut.transaction.annotation.TransactionalEventListener
 import io.micronaut.transaction.annotation.TransactionalEventListener.TransactionPhase
 import org.slf4j.LoggerFactory
 import javax.inject.Singleton
+import javax.transaction.Transactional
 
 typealias SomethingId = Int

正如你从这个大块中看到的那样:

  • package 行的更改已正确报告
  • 已正确报告添加了 Transactional 导入
  • 没有提及删除SomethingFacade 行!

当尝试应用补丁 git 失败时说“它不匹配”..

我尝试使用-C 2/1/0 生成补丁,但它们都以某种方式失败(注意:我正在为整个目录生成一个补丁。使用-C 0 我相信这个文件可以工作,但无数其他文件可以不是)。

我可以做git apply --3way 并手动修复问题,但这样做实际上并没有发现问题...结果是:

package other.my.application

import io.micronaut.runtime.event.annotation.EventListener
import io.micronaut.transaction.annotation.TransactionalEventListener
import io.micronaut.transaction.annotation.TransactionalEventListener.TransactionPhase
import it.my.application.SomethingFacade
import org.slf4j.LoggerFactory
import javax.inject.Singleton
import javax.transaction.Transactional

typealias SomethingId = Int

所以关于SomethingFacade 的行被留下了。这是此文件的合并输出:

Checking patch src/main/kotlin/it/my/application/Something.kt => src/main/kotlin/other/my/application/Something.kt...
error: while searching for:
package it.my.application

import io.micronaut.runtime.event.annotation.EventListener
import io.micronaut.transaction.annotation.TransactionalEventListener
import io.micronaut.transaction.annotation.TransactionalEventListener.TransactionPhase
import org.slf4j.LoggerFactory
import javax.inject.Singleton

typealias SomethingId = Int


error: patch failed: src/main/kotlin/it/my/application/Something.kt:1
Falling back to three-way merge...

git 不应该生成:

--- a/src/main/kotlin/it/my/application/Something.kt
+++ b/src/main/kotlin/other/my/application/Something.kt
@@ -1,10 +1,11 @@
-package it.my.application
+package other.my.application
 
 import io.micronaut.runtime.event.annotation.EventListener
 import io.micronaut.transaction.annotation.TransactionalEventListener
 import io.micronaut.transaction.annotation.TransactionalEventListener.TransactionPhase
-import it.my.application.SomethingFacade
 import org.slf4j.LoggerFactory
 import javax.inject.Singleton
+import javax.transaction.Transactional
 
 typealias SomethingId = Int

或类似的东西:

--- a/src/main/kotlin/it/my/application/Something.kt
+++ b/src/main/kotlin/other/my/application/Something.kt
@@ -1,3 +1,3 @@
-package it.my.application
+package other.my.application
 
 import io.micronaut.runtime.event.annotation.EventListener
@@ -4,7 +4,8 @@
 import io.micronaut.transaction.annotation.TransactionalEventListener
 import io.micronaut.transaction.annotation.TransactionalEventListener.TransactionPhase
-import it.my.application.SomethingFacade
 import org.slf4j.LoggerFactory
@@ -7,10 +8,11 @@
 import javax.inject.Singleton
+import javax.transaction.Transactional
 
 typealias SomethingId = Int

?

为什么它直接忽略SomethingFacade 行?


附加信息(不确定这是否相关):

A 标记位于 master 分支的先前提交上,其内容与 B 分支的 HEAD 相同。 B 分支是从先前版本的 master 创建的,其中所有提交都被压缩为一个提交。

分支B 的要点是它应该隐藏提交活动和原始提交的作者。我们通过将所有新提交压缩到B 中的单个提交来定期同步masterB。所以分支Bmaster 没有共同的历史但是 对于B 的每个提交,都有一个master 的提交,其内容是相同的。 我不确定这是否会导致git diff 出现问题...我已在其他代码库中成功使用此方法而没有问题。

【问题讨论】:

    标签: git kotlin diff patch


    【解决方案1】:

    要获得特定的 diff 输出,diff 在此处比较的文件必须将这些特定文本作为输入。也就是说,git diff 在此处比较的文件任一文件中有import it.my.application.SomethingFacade

    请注意,您可以查看正在比较的两个文件,因为它们的 blob 哈希 ID 由 index 行给出:

    index ed24736..cb13606 100644
    

    左侧文件为 Git 内部 blob ed24736,右侧文件为 Git 内部 blob cb13606

    (这两个不同的文件可能包含在许多不同的提交中,因为 Git 会删除每个提交中出现的提交副本。所以这里不知道比较了哪些 提交;所有我们知道,从git diff 输出中,正在比较哪些blob 对象。但是您的git diff 命令通常会指定要比较的两个提交:in

    git diff <hash1> <hash2>
    

    例如,这里出现的两个hash-es 是相关提交的哈希 ID。

    如果您使用标签名称,例如:

    git diff v1.2 v3.4
    

    如果您愿意,可以让 Git 解析标签名称以提交哈希 ID,使用 git rev-parse v1.2git rev-parse v3.4。不过,无论哪种方式,我们从实际的 git diff 输出中知道,被比较的 文件 具有两个给定的 blob 哈希 ID。

    【讨论】:

    • 补丁由git diff --patch A..master制作。执行git checkout A 文件确实 包含该行。我想知道:使用A..masterA master 作为两个单独的参数有什么区别?
    • @GACy20: no: A..masterA master 应该以完全相同的方式解析 git diff。如果没有,您已经遇到了(不太可能但可能)Git 中存在实际错误的情况,并且如果有问题的存储库可供公众使用,您可以将复制者发送到 Git 邮件列表,并带有错误报告。
    • 分支Bmaster 在提交方面没有共同祖先这一事实是否有任何相关性?我很想尝试使用普通的diff,通过将存储库复制到 2 个不同的目录来生成补丁...
    • 如果你的意思是git diff --patch,没有。通常,缺乏共同祖先意味着A..master(或B..master,或master..B,或其他)有点没有意义,但在git diff中,它只需要git rev-parse的内部结果并注意到它以^&lt;rev-of-A&gt; &lt;rev-of-master&gt; 出现,并使用否定的作为左侧,使用非否定的作为右侧。 Diff 在内部对X...Y 的处理方式类似:变为 ^|LEFT |RIGHT 并选择其中一个基作为左侧, 作为右侧。
    • 如果您的意思是 应用生成的补丁,那么实际来源当然很重要,任何 index 行的存在以及 blob(s ) 这些索引行中列出的内容存在于存储库中。当你得到error: patch failed: src/main/kotlin/it/my/application/Something.kt:1 Falling back to three-way merge... 这意味着合并没有按原样应用,Git 需要找到原始文件,对其应用补丁,并将其用作theirs三路合并。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-13
    • 1970-01-01
    • 2015-05-21
    • 1970-01-01
    • 2018-08-25
    • 1970-01-01
    • 2011-03-26
    相关资源
    最近更新 更多