注意行尾的结尾git diff
:
- IP_ADDR: 'http://1.2.3.4:143'
+ IP_ADDR: 'http://2.4.6.8:143'^M
我通过将光标放在上面1
然后按下ct:
并输入新的 IP 地址来编辑此文件。没有在文件中添加或删除完整的行。不过我确实注意到该文件dos
在 VIM 中显示为类型。
如果我没有明确编辑文档的该部分,为什么 VIM 会更改行尾?另外,看到原始行中diff
没有显示^M
,VIM 还能如何确定这是一个dos
文件?
答案1
Vim 将检测原始文件格式(在 中配置的格式中'fileformats'
),并使用相同的格式进行写入。Vim 切换(例如从 Unix 切换到 Windows 风格)的唯一方法是通过显式:setlocal fileformat=dos
。您的配置中不太可能有这个;:verbose setl ff?
可以告诉您。
我不会太在意 Git diff 本身(只要不是全部如果行看起来已更改,则实际上切换了行尾),而是提交了正确的内容。
请注意,使用 Git 设置autocrlf = true
,Git 会在签出文件时将换行符转换为系统标准,并在提交时转换为 LF 换行符。因此,一切可能都很好,只有 Git diff 输出会让您感到困惑。
答案2
这证明我们都生活在黑客帝国中。如果这真的是 21 世纪,那么我们就不会还在为不同的行尾而战。
Vim 在处理行尾方面做得相当不错。详细信息请参阅下文:help 'ffs'
。当然,vim 无法读懂你的想法:如果你的文件有不一致行结尾,那么 vim 可能不会按照你想要的方式运行。
我建议在 vim 中打开文件然后
:e! ++ff=unix
这将从磁盘重新加载文件,强制 vim 使用 unix 样式的行尾。然后您应该能够准确看到哪些行有 CRLF 结尾,因为它们将以原始^M
字符结尾。
虽然我喜欢 git,但我对它的了解和信任程度不如 vim。我认为有些人建议对 git 的crlf
设置采用“设置后就忘掉”的配置,这可能会导致混淆。我更愿意避免 @Ingo Karkat 在他的回答中提到的设置。我希望 git 签出签入的同一个文件,让我(和 vim)处理行尾。
答案3
git diff
仅在添加的行中显示回车符 ( ^M
),而不在删除或未更改的行中显示回车符。如果您使用标志-R
,则可以看到这一点,该标志会以相反的方式显示差异。
$ git diff -R
:
- IP_ADDR: 'http://2.4.6.8:143'
+ IP_ADDR: 'http://1.2.3.4:143'^M
因此 vim 不会添加任何内容;尤其是不会只添加一行。Vim 在打开文件时会使用在文件中找到的行尾。
答案4
vim是根据fileformat选项的值来判断当前打开的文件是dos还是unix,或者是mac文件。fileformat选项的值由fileformats选项的值决定。
当 vim 打开一个文件时,vim 会根据当前 fileformats 选项的值来确定当前缓冲区有效的 fileformat 选项值。vim 手册中关于 vim 如何根据 fileformats 选项的值来确定当前缓冲区的 fileformat 选项值的描述如下:
'fileformats' 'ffs' string (default:
Vim+Vi MS-DOS, MS-Windows OS/2: "dos,unix",
Vim Unix: "unix,dos",
Vim Mac: "mac,unix,dos",
Vi Cygwin: "unix,dos",
Vi others: "")
global
{not in Vi}
This gives the end-of-line (<EOL>) formats that will be tried when
starting to edit a new buffer and when reading a file into an existing
buffer:
- When empty, the format defined with 'fileformat' will be used
always. It is not set automatically.
- When set to one name, that format will be used whenever a new buffer
is opened. 'fileformat' is set accordingly for that buffer. The
'fileformats' name will be used when a file is read into an existing
buffer, no matter what 'fileformat' for that buffer is set to.
- When more than one name is present, separated by commas, automatic
<EOL> detection will be done when reading a file. When starting to
edit a file, a check is done for the <EOL>:
1. If all lines end in <CR><NL>, and 'fileformats' includes "dos",
'fileformat' is set to "dos".
2. If a <NL> is found and 'fileformats' includes "unix", 'fileformat'
is set to "unix". Note that when a <NL> is found without a
preceding <CR>, "unix" is preferred over "dos".
3. If 'fileformat' has not yet been set, and if a <CR> is found, and
if 'fileformats' includes "mac", 'fileformat' is set to "mac".
This means that "mac" is only chosen when:
"unix" is not present or no <NL> is found in the file, and
"dos" is not present or no <CR><NL> is found in the file.
Except: if "unix" was chosen, but there is a <CR> before
the first <NL>, and there appear to be more <CR>s than <NL>s in
the first few lines, "mac" is used.
4. If 'fileformat' is still not set, the first name from
'fileformats' is used.
When reading a file into an existing buffer, the same is done, but
this happens like 'fileformat' has been set appropriately for that
file only, the option is not changed.
When 'binary' is set, the value of 'fileformats' is not used.
When Vim starts up with an empty buffer the first item is used. You
can overrule this by setting 'fileformat' in your .vimrc.
For systems with a Dos-like <EOL> (<CR><NL>), when reading files that
are ":source"ed and for vimrc files, automatic <EOL> detection may be
done:
- When 'fileformats' is empty, there is no automatic detection. Dos
format will be used.
- When 'fileformats' is set to one or more names, automatic detection
is done. This is based on the first <NL> in the file: If there is a
<CR> in front of it, Dos format is used, otherwise Unix format is
used.
Also see |file-formats|.
For backwards compatibility: When this option is set to an empty
string or one format (no comma is included), 'textauto' is reset,
otherwise 'textauto' is set.
NOTE: This option is set to the Vi default value when 'compatible' is
set and to the Vim default value when 'compatible' is reset.
回到你的问题,你的文件在vim中被识别为dos文件,所以当你保存文件并退出vim时,vim会自动将换行符替换为dos样式的换行符:。
在你的 git 工作目录树中,这个文件是一个 dos 文件,但是由于这个文件在 git 索引树中是一个 unix 文件,所以,使用git diff
,你会看到文件已经发生了变化。对于 Unix 格式的文件,多余的部分将显示为 ^M 字符。