Git错误:"致命错误:第36行处的补丁文件损坏"

38

我有一个Java文件,以这样的方式结束:

    }
}

我之前不小心删除了末尾的换行符,但直到今天提交时才收到Git-GUI的错误消息。

fatal: corrupt patch at line 36

我尝试添加缺失的换行符,但是Git似乎无法正确处理它:

添加换行符之前:

     }
 }
\ No newline at end of file

添加换行符后:

     }
-}
\ No newline at end of file
+}

它仍然给我那个错误。

我尝试回滚更改并仅添加换行符而没有对文件进行其他更改,但也没有帮助。

编辑:添加两个甚至三个换行符也没有帮助。

编辑2:此错误仅在提交最后一块中的行时出现。


@LucasEasedUp:解决方案很简单。从命令行提交。 - Jan Hudec
1
注意:我默认您是从命令行提交的。如果您是从“git gui”提交的,并且没有尝试过从命令行提交,请在报告中提及并尝试使用命令行提交,然后报告是否有效。 - Jan Hudec
@JanHudec 我编辑了我的问题并提到我已经使用了Git Gui。 - wassup
请查看我在 https://dev59.com/2Gct5IYBdhLWcg3wXsMy#19790903 上的答案。 - Zonko
1
如果您在类UNIX系统上创建补丁并尝试在Windows上应用它,则会遇到典型的EOL问题。我不得不使用编辑器(在这种情况下是VS Code)将其从CRLF更改为LF,之后git apply就可以正常工作了。 - sakisk
显示剩余2条评论
9个回答

41

当您编辑“-”行时会出现这种情况。
当您删除“-”并忘记添加空格时

打开您的补丁并检查所有您想保留不变的行是否以“ ”(空格)开头

更新

您的编辑器可能还有选项:“删除行末空格”。因此,当您在编辑器中保存补丁时:

-Line with space at end <--- NOTICE: Here there is one space at the end
+Line with no space at end<--- Here there's no space

你的编辑器将删除行末空格并进行修补,结果如下:

-Line with space at end<--- Here no space. Patch will FAIL!!!
+Line with no space at end<--- Here no space also

这个补丁会失败,因为原文件中没有这一行:

-Line with space at end<---

相反,它具有:

-Line with space at end <--- 

更新
有时您希望删除-行。您可以通过修剪的空格将其更改为不起作用(这里只是以空格作为第一个字符):

 
为了解决这个问题,只需在它后面添加+行即可:

要解决此问题,只需在其后添加+行即可:

-
+

这个补丁将删除空行,然后再添加回来。


1
这将指出补丁不适用,而不是它已损坏。 - Joost
3
哇,就像添加一个只有空格的额外行一样,我的补丁得以应用。 - Jake88
@Jake88 这是因为补丁中的第一个字符是特殊字符:' '(空格)保留行不变,'+' 表示这一行是新添加的,'-' 表示这一行将被删除,'' 表示文件末尾没有换行符。有些编辑器会删除行末的空格,但这对于补丁来说非常重要。 - Eugen Konkov
1
@DaBooba:你可以配置编辑器,仅针对你更改的行删除尾随空格。这在许多现代编辑器中都得到了支持。 - Eugen Konkov
1
@DaBooba:要删除 - 行,你只需要在它后面添加 + 行即可;-) 请参见 UPD - Eugen Konkov
显示剩余4条评论

15

另一个可能的问题,特别是在使用普通文本编辑器进行编辑时,是无法处理hunk开头的数字的,这些数字表示旧代码中有多少行和新代码中有多少行,以及每个文件从哪里开始。如果这些数字不匹配,就会出现fatal: corrupt patch at line x错误。

例如,@@ -32,9 +54,15 @@表示要在第32行找到要替换的代码,并且需要在原始文件中连续的9行中进行替换,但是在编辑后的文件中,需要从第54行开始连续替换15行。如果添加或删除任何行,则还需要编辑这些数字。

虽然我没有做过任何真正的研究或使用过git gui,但有可能,由于某些标准认为没有以换行符结尾的行不是技术上的行,因此您需要更改其中一个或两个数字才能正确应用补丁。


3
我之前遇到了损坏的补丁错误,原因是因为换行符的问题。虽然Notepad++显示每行末尾都有LF(换行符),但这并不是完全正确的。
在我的Ubuntu虚拟机上,我运行了cat -A mypatch.patch | less命令来查找不需要的字符。损坏的补丁文件以^M$(Windows换行符)结尾,而不是$。
我通过apt install dos2unix安装了dos2unix工具。
(这是一款用于将带有DOS或MAC换行符的文本文件转换为Unix换行符或反之的工具)
然后,我运行了dos2unix mypatch.patch命令,补丁成功应用了。

2

commit 命令不会对补丁做任何处理,甚至不会处理它们的内容。commit 命令只会格式化树和提交对象并调整 HEAD 和它所指向的引用。因此,是导致此错误的不是 commit 命令本身。

也不是 add 命令,因为虽然它会哈希新文件内容,但它只操作新内容,完全不关心差异。

唯一关心差异的是默认的 pre-commit 钩子,该钩子检查您是否添加了尾随空格等类似问题。您可以通过调用 git commit --no-verify 来跳过该检查。但是,您必须首先启用它,并且您可能已经知道了这一点。


2
不是直接回答你的问题,但我刚刚在运行git apply something.diff时遇到了这个错误,并且解决方案与你的描述相似,所以我认为应该在这里发布供未来的使用者参考: something.diff在末尾没有空行。显然,最后的换行符对于git很重要,一旦我添加了它,它就起作用了。

1

我最近遇到了一个类似的问题(可能是由于git gui的工作方式相同),这个问题对任何遇到它的人都可能有用。

当我通过 git add -e pom.xml 来打补丁我的 pom.xml 文件时,补丁如下。

diff --git a/pom.xml b/pom.xml
index 3dba69a..a9c8ebb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,26 +1,48 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <groupId>adowrath</groupId>
     <artifactId>project-name</artifactId>
     <version>0.0.1</version>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
     <build>
         <sourceDirectory>src/main/java</sourceDirectory>
         <testSourceDirectory>src/test/java</testSourceDirectory>
         <plugins>
             <plugin>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <version>3.6.1</version>
                 <configuration>
                     <source>1.8</source>
                     <target>1.8</target>
                 </configuration>
             </plugin>
             <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <version>0.7.9</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>report</id>
+                        <phase>test</phase>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
                 <artifactId>maven-surefire-plugin</artifactId>
                 <version>2.16</version>
                 <configuration>
                     <includes>
                         <include>**/Test*.java</include>
                         <include>**/*Test.java</include>
                         <include>**/*Tests.java</include>
@@ -32,9 +54,15 @@
     </build>
     <dependencies>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <version>4.12</version>
         </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>2.5.5</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>

我想删除最后一个依赖项中的Mockito。如果我只是删除这些行,它总是会报告到第64行出错:

fatal: corrupt patch at line 64
fatal: Could not apply '.git/ADD_EDIT.patch'

第64行是补丁文件中的最后一行,因此是<project>之后的那一行

解决方案很简单,只需删除整个主干,从@@-行开始往下的所有内容,它将立即生效。

希望这可以帮到你。


1

And I wanted to remove the last block with the Mockito-dependency.
If I just remove the lines itself, it always gives me an error reporting to line 64:

fatal: corrupt patch at line 64
fatal: Could not apply '.git/ADD_EDIT.patch'
现在(2019年第一季度)使用Git 2.21+,您不应该再看到那种错误了,因为在2.21之前,“git add -e”在要让用户编辑的更改比临时文件中留下的先前更改小时会感到困惑。

add --edit: 截断补丁文件

如果已经存在一个“.git / ADD_EDIT.patch”文件,则我们无法正确截断它,这可能会导致非常有趣的错误。

当然,这个文件不应该被留在那里。
但至少在某些情况下,存在一个过时的副本,比当前差异大。所以结果是一个损坏的差异。

让我们在编写文件时截断文件,并不要过于担心它。


1
我曾经遇到过同样的问题,最后终于找出了原因。我的某些行缩进使用了制表符而不是空格。将所有缩进都改为空格后,问题得以解决。

0

好的,抱歉没有仔细检查。

我尝试了像平常一样添加和提交,但是没有使用Git-GUI,而是使用命令行,它起作用了。

因此,我建议所有遇到Git-GUI问题的人在发布之前先通过命令行进行检查,不要像我这样做。


好的信息,谢谢!顺便说一句,你可以接受自己的答案,因为它解决了问题。 - Useless
4
它没有回答问题所在以及为什么问题被解决。 - Eugen Konkov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接