15

我正在尝试对我的 repo 应用一些补丁,并获取消息patch does not apply,除非我指定 params --ignore-space-change --ignore-whitespace。即使使用这些密钥也无法应用某些补丁,它表示存在需要手动解决的冲突。(但实际上那里没有冲突,自动合并必须解决这个问题)

我做了一个实验:从我的 repo 中的提交创建一个补丁,将 master 重置为上一个提交,尝试从文件中应用补丁。同样的错误信息。

任何想法,为什么会发生这种情况?

UPD 命令非常简单:

git format-patch -o ../_patches 0f3bf7874c32b22256ae2d9dc00b1afd6464e43c
git reset --hard 0f3bf7874c32b22256ae2d9dc00b1afd6464e43c
git am ../_patches/0001-test2.patch

(这个 id 是指最后一次之前的第一次提交)

4

2 回答 2

16

您需要将--keep-cr标志传递给git am. 这很不幸,但由于存在竞争标准(电子邮件工作流程与本地),确实没有太多选择。

您可能还想尝试设置.gitattributes文件。尝试重新创建您的问题,当我将文件指定为需要 CRLF 时,我能够让事情正常工作。请注意,在没有首先规范化文件的情况下,它确实将整个文件显示为已修改。我通常使用 a .gitattributes

.gitattributes  export-ignore
.gitignore      export-ignore

*.txt           text
*.C             text trailing-space space-before-tab -indent-with-non-tab
*.rst           text trailing-space space-before-tab -indent-with-non-tab
*.clj           text trailing-space space-before-tab -indent-with-non-tab

*.c             text diff=cpp trailing-space space-before-tab -indent-with-non-tab
*.cpp           text diff=cpp trailing-space space-before-tab -indent-with-non-tab
*.h             text diff=cpp trailing-space space-before-tab -indent-with-non-tab
*.hpp           text diff=cpp trailing-space space-before-tab -indent-with-non-tab
*.py            text diff=python trailing-space space-before-tab -indent-with-non-tab
*.tex           text diff=tex
*.java          text diff=java trailing-space space-before-tab -indent-with-non-tab
*.pl            text diff=perl trailing-space space-before-tab -indent-with-non-tab
*.php           text diff=php
*.rb            text diff=ruby trailing-space space-before-tab -indent-with-non-tab

*.vcproj        eol=crlf
*.dsp           eol=crlf
*.dsw           eol=crlf

*.sh            eol=lf

*.jpg           binary
*.png           binary
*.gif           binary
*.tiff          binary

您需要根据gitattributes 手册页规范您的行尾。另一个 SO 用户最终也关闭了core.autocrlf获取干净的提交和补丁。

试图重现你的错误

$ git init repo
Initialized empty Git repository in c:/tmp/git-eol/repo/.git/
$ cd repo
$ git config --local core.autocrlf false
$ vim foo.txt
$ git add foo.txt
$ git commit -m "Add foo."
[master (root-commit) 3903abd] Add foo.
 1 file changed, 3 insertions(+)
 create mode 100644 foo.txt
$ vim foo.txt
$ git st
## master
 M foo.txt
$ git commit -m "Add more foo." -a
[master 03e991a] Add more foo.
 1 file changed, 2 insertions(+)
$ git format-patch HEAD~1
0001-Add-more-foo.patch
$ vim 0001-Add-more-foo.patch

查看生成的补丁文件,我看到:

如您所见,回车符 ( ^Ms) 保留在补丁中。这是与core.autocrlf=false. 继续,我看到:

$ git reset --hard HEAD~1
HEAD is now at 3903abd Add foo.
$ git am 0001-Add-more-foo.patch
Applying: Add more foo.
error: patch failed: foo.txt:1
error: foo.txt: patch does not apply
Patch failed at 0001 Add more foo.
The copy of the patch that failed is found in:
   c:/tmp/git-eol/repo/.git/rebase-apply/patch
When you have resolved this problem, run "git am --resolved".
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 am --abort

所以补丁不能很好地开箱即用。使用--keep-cr符合预期:

$ git am --keep-cr 0001-Add-more-foo.patch
Applying: Add more foo.
$

好的。因此,让我们尝试一下core.autocrlf=true(在不同的存储库中):

# Removed the initial commands...
$ git format-patch HEAD~1
0001-Add-more-foo.patch
$ git reset --hard HEAD~1
HEAD is now at 525b5aa Initial commit.
$ git am 0001-Add-more-foo.patch
Applying: Add more foo.
$ git config --get core.autocrlf
true

在这种情况下,补丁到处都有 LF 结尾。

于 2013-04-22T10:13:12.760 回答
2

啊哈!看来我已经找到原因了。存储库使用 CRLF 行结尾,但 format-patch 使用 LF 创建补丁文件。当我使用 autocrlf=false 从头创建一个仓库并进行相同的实验时,我遇到了同样的问题。(看起来像 Git 中的一个错误)
任何建议如何解决这个问题?

UPD 我的解决方案是使用 autocrlf=true 创建一个新的存储库,然后将两个存储库中的所有更改重新导入其中。

于 2013-04-22T09:52:53.930 回答