如何修复使用 "git diff" 显示 ^M 但使用 vim/gedit/cat -e 看起来不错的已更改源代码行?

How to fix changed source lines showing ^M with "git diff" but look fine with vim/gedit/cat -e?

我四处寻找询问类似问题的人。它 而不是 似乎是 :set fileformat=dos:set fileformat=unix.

的简单情况

:set fileencoding=latin1:set fileformat=dos 写出文件已更改,这样 git diff 报告所有行都附加了 ^M。

代码最初很高兴地存在于:

...
if (v == value32S)
{
...

我对(在 vim 的屏幕上看起来不错)进行了彻底的改进:

...
if (v == value32S ||
    v == value33)
{
...

但是 git diff 检查错误更改显示:

diff --git a/csettings.cpp b/csettings.cpp
index 1234..8901 100755
--- a/csettings.cpp
+++ b/csettings.cpp
@@ -2466,7 +2466,8 @@ bool MyClass::settingIsValid(QString s)

#if CONFIG_1 || CONFIG_2

-       if (v == value32S)
+       if (v == value32S ||^M
+           v == value33)^M
        {
              doSomething(new_v);

其中粗体斜体文本是反白视频。

我试过几种方法让这辆看似虚假的马车returns走开。首先是确定没有隐藏角色。查看 vim :set list:

...
if (v == value32S ||$
    v == value33)$
{$
...

看起来不错。转储文件(微细节因保护NDA而有所不同,我懒得让它成为一个完美的欺骗):

$ hd csettings.cpp
(...)
0000eae0 xx xx xx xx xx xx xx xx  xx 65 33 32 53 20 7c 7c  |(v == value32S |||
0000eaf0 0d 0a 20 20 20 20 20 20  20 20 20 20 20 20 76 20  |..             v |
0000eb00 3d 3a 20 xx xx xx xx xx  xx 65 33 33 29 0d 0a 20  |== ...value33).. |

All 其他行也以“0d 0a”结尾,所以这看起来不错。一个有趣的建议是使用 cat -e(这对我来说是新的):

$ cat -e c.cpp

...
if (v == value32S ||^M$
    v == value33)^M$
{^M$
...

另一个建议是使用 file 作为线索:

$ file csettings.cpp
csettings.cpp:  C source, UTF-8 Unicode text, with CRLF line terminators

有趣的是,这是该目录(头文件和 cpp 代码)中唯一不是 ASCII text 的文件。有些文件有 CRLF 行终止符,有些则没有。此外,有些显示 C++ source,其他显示 C source,我认为这并不重要。

删除文件并 git checkout 获取新副本也将其显示为 UTF-8,我追踪到某些字符串(“°F”和“°C”)中有度数符号,所以UTF-8 似乎不是问题。

不过,我不明白为什么使用 vim 编辑 只有这些行 会导致这个问题。或者这可能不是问题?有什么想法吗?

----- 附录 -----

git config --get-regexp core.* 显示

core.repositoryformatversion 0
core.filemode true
core.bare false
core.logallrefupdates true

假设您使用的是基于 unix 的操作系统。 通常使用 vi 或 cat 命令,^M 字符是不可见的。 您可以使用 cat -v 命令查看。 例如。 cat -v < file_name >

要删除这些字符,请使用 dos2unix 命令。 例如。 dos2unix < file_name >

这将删除那些 ^M 字符并将结果保存在同一个文件中。因此您不必创建任何临时文件来存储中间文件内容。

默认情况下,Git 假定您在存储库中使用 Unix 行结尾并突出显示回车符 returns 作为尾随空格。但是,默认情况下,它仅在新行上突出显示尾随空格,因为目标是避免引入 new 问题。

如果你 运行 git diff --ws-error-highlight=all,你会看到在被删除的行和上下文行上也有回车符 returns。如果你不想看到这个,你可以将core.whitespace设置为cr-at-eol,这将阻止它被突出显示。对此没有不良影响;它只是防止回车 returns 被视为尾随空格。

如果您计划在非 Windows 系统上使用此项目,您应该将行结尾转换为 Unix 并使用 .gitattributes 文件指定 text 属性对于文本文件,行尾会根据使用的操作系统自动转换。即使您的项目仅在 Windows 上使用,这也可能很有价值,因为如果有人设置了 core.autocrlf,您最终可能会得到混合行结尾。