git status 显示修改,即使 autocrlf=false

42
我遇到了与此问题相同的问题:git status显示修改,git checkout --<file>不能删除它们 即使使用git config --global core.autocrlf false,Git仍然显示工作目录中的修改:
E:\_dev\github\Core [master +0 ~93 -0]> git config --get-all core.autocrlf
false
false

请注意,我甚至将--system设置为false

为什么Git似乎仍在修改我的行末?

尝试消除修改

基线

E:\_dev\github\Core [master +0 ~93 -0]> git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   tools/StatLight/StatLight.EULA.txt
... more changes ...
no changes added to commit (use "git add" and/or "git commit -a")

git checkout -- .

E:\_dev\github\Core [master +0 ~93 -0]> git checkout -- .
E:\_dev\github\Core [master +0 ~93 -0]> git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed) 
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   tools/StatLight/StatLight.EULA.txt
... more changes ...
no changes added to commit (use "git add" and/or "git commit -a")

有时这会以奇怪的方式产生影响:

E:\_dev\github\Core [master +0 ~628 -0]> git checkout -- .
E:\_dev\github\Core [master +0 ~361 -0]> git checkout -- .
E:\_dev\github\Core [master +0 ~93 -0]> git checkout -- .
E:\_dev\github\Core [master +0 ~93 -0]> git checkout -- .
E:\_dev\github\Core [master +0 ~93 -0]> git checkout -- .

git reset --hard

E:\_dev\github\Core [master +0 ~93 -0]> git reset --hard
HEAD is now at 11a7f9a Merge pull request #8 from RemiBou/master
E:\_dev\github\Core [master +0 ~93 -0]>

git add .; git stash; git stash drop

E:\_dev\github\Core [master +0 ~93 -0]> git add .
... warnings ....
warning: CRLF will be replaced by LF in tools/StatLight/StatLight.EULA.txt.
The file will have its original line endings in your working directory.

E:\_dev\github\Core [master +0 ~93 -0]> git stash
Saved working directory and index state WIP on master: 11a7f9a Merge pull request #8 from 
RemiBou/master
HEAD is now at 11a7f9a Merge pull request #8 from RemiBou/master

E:\_dev\github\Core [master +0 ~93 -0]> git stash drop
Dropped refs/stash@{0} (de4c3c863dbad789aeaf563b4826b3aa41bf11b7)

E:\_dev\github\Core [master +0 ~93 -0]> git status .\tools\StatLight\StatLight.EULA.txt
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   tools/StatLight/StatLight.EULA.txt
#
no changes added to commit (use "git add" and/or "git commit -a")

我有一个问题在这里 - 它们可能是相同的问题。在我的问题中,我还验证了没有gitattributes干扰。 - djechlin
@djechlin 你可以把 git config -l 的输出放到 pastebin 上并在此处链接吗?确保在项目根目录或任何其他文件夹中没有 .gitattributes。 - Chronial
6个回答

24
这似乎是msysgit的一个bug。作为解决方法,请尝试创建一个包含以下内容的.gitattributes文件。
* -text

这将告诉Git不对任何文件执行EOL转换。

2
似乎这个错误不仅限于msysgit。在Mac OS X上也很容易重现:http://stackoverflow.com/questions/22823004/files-incorrectly-reported-modified-git-attributes-buggy-leading-to-inconsist - gatinueta
1
在查看了数十个关于Git和行尾的StackOverflow帖子后,这是唯一拯救我的一个! - donquixote
在我的情况下没有帮助,即使我在.git/info下有一个包含上述内容的属性文件并且设置了"core.autocrlf false",git仍然显示文件已修改。 - DannyS

10

检查是否没有.gitattributes文件

gitattributes手册的"Effect"部分所述, 这些文件也可以对eol和自动转换产生影响:

text ^^^^^^

该属性启用并控制行尾规范化。当文本文件被规范化时,其行结束符会在存储库中转换为LF。要控制工作目录中使用的行结束符样式,请对单个文件使用eol属性和core.eol配置变量以适用于所有文本文件。请检查您的配置文件中的core.eol,如“如何在不同操作系统之间使用git core.autocrlf进行行结束符转换”所述。

Git 2.41(2023年第二季度)包含文档更新,以澄清文本和eol属性如何交互以指定行尾转换。

请参见提交6696077(2023年5月2日),作者为Alex Henrie(alexhenrie
(由Junio C Hamano -- gitster --合并于提交c05615e,2023年5月10日)

文档:重写文本和 eol 属性的文档

协助者:Torsten Bögershausen
签名者:Alex Henrie

这两个句子很容易让人混淆,因为text属性的描述与text=auto属性的描述完全相同:
“在路径上设置text属性可以启用行尾规范化”
“当text设置为“auto”时,该路径被标记为自动行尾转换”
除非读者已经熟悉这两种变体,否则他们很可能会认为“行尾规范化”和“自动行尾转换”是相同的东西。
此外,在text=auto段落中的短语“当文件已经使用CRLF提交时,不进行转换”并不适用于早期描述的裸文本属性。
而且,它错误地暗示了只有在文件已提交的情况下才会抑制规范化。
实际上,在CRLF文件上运行git add(man),将text=auto属性添加到文件中,然后再次运行git add也不会对行结尾做任何处理。
此外,在eol属性的多个文档中,听起来似乎它不会影响检入时的规范化或者它会强制检入时的规范化。
它还听起来像是必须设置eol(或设置配置变量)才能在检出时打开转换,但是如果未指定eol,则text属性本身就可以在检出时打开转换。
重新表述text、text=auto、eol、eol=crlf和eol=lf的文档,明确它们如何相同,如何不同以及在哪些情况下执行转换。

gitattributes现在在其man page中包括:

此属性将路径标记为文本文件,启用行尾转换:当匹配的文件添加到索引时,在索引中规范化文件的行尾到LF。相反,当文件从索引复制到工作目录时,其行尾可能会根据eol属性、Git配置和平台转换为CRLF(请参见下面有关eol的说明)。

gitattributes现在在其man page中包括:

与上述描述一样,在签入和签出时进行转换。每次签入文件时,索引中的行尾都会规范化为 LF,即使该文件以 CRLF 行尾添加到 Git 中。
现在,gitattributes 在其手册页面中包括以下内容:

text 设置为 "auto" 时,Git 自行决定文件是文本还是二进制文件。如果它是文本文件,并且该文件之前没有使用 CRLF 行尾添加到 Git 中,则在签入和签出时将进行行尾转换,如上所述。否则,在签入或签出时不进行转换。

现在,gitattributes 在其手册页面中包括以下内容:
这个属性标记了在工作树中检出时使用特定行尾样式的路径。它只有在设置了texttext=auto(见上文)时才会生效,但如果未指定text,则指定eol会自动设置text
现在gitattributes已在其手册页面中包含以下内容:
此设置将文件的行尾在工作目录中转换为CRLF,当文件被检出时。
现在gitattributes已在其手册页面中包含以下内容:

此设置在文件检出时,使用与索引相同的行尾符号。

未指定

如果文件的eol属性未指定,则其工作目录中的行尾符号由core.autocrlfcore.eol配置变量确定(请参见git config中这些选项的定义)。如果设置了text但没有设置这些变量,则默认情况下,在Windows上为eol=crlf,在其他所有平台上为eol=lf


1
@codekaizen 好的。这个想法是不要设置任何core.eol.gitattributes text指令,并保持auto.crlffalse。如果这仍然无法防止eol转换,那么我们可以消除它们并继续寻找。 - VonC
最近几天也遇到了同样的问题,还没有找到可行的解决方案吗? - Rangel Reale
@core24 我不知道有什么解决方法。如果您能够稳定地重现该问题,并提供一个的示例,请在https://github.com/msysgit/msysgit/issues上提交错误报告。 - VonC
@RangelReale 我不知道任何可行的解决方案。如果您能够使用示例稳定地重现此问题,请在https://github.com/msysgit/msysgit/issues上提交错误报告。 - VonC
@VonC - 如我以上所述,问题可以可靠地再现。如果Rangel或core24想要通过创建问题来帮助,我可以填写有关我在那里使用的文件的详细信息。 - codekaizen
显示剩余6条评论

8

我正在调查MSysGit中核心功能core.autocrlf的异常行为,并发现以下设置:

[core]
    autocrlf = false
    safecrlf = true
    ignorecase = true
    eol = native 

在全局配置文件中,以及从另一台计算机复制(而不是克隆)的存储库中没有设置core.autocrlf时,发出git status命令会导致所有文本文件标记为已修改(周围没有gitattributes)。

但是,如果将本地(存储库)core.autocrlf设置为true,然后发出git status命令,所有更改都会消失,存储库变回干净状态

但是,在删除刚添加的存储库配置文件中的core.autocrlf设置(因此返回到精确的初始状态)之后,git status命令仍继续报告未更改内容

考虑到存储库上没有执行任何操作,只是更改了一个配置设置并恢复到原始状态,这就做到了......

如果这不是错误,我无法想象世界上谁会认为这是“正常”的行为。


6
这个问题可能是由于gitattributes的text选项引起的。
请仔细阅读文档,但基本上只有当在.gitattributes中未设置text时,autocrlf才有作用:

未指定
如果未指定text属性,则git使用core.autocrlf配置变量来确定是否应该进行文件转换。

通过以下方式找到您的.gitattributes文件:
find <root-dir> -name .gitattributes

使用 grep 命令查找 texteolcrlf 以找到问题并根据需要进行修订。

您可以更改此文件,然后在提交之前撤消这些更改,以便足够长的时间解决您的问题。


1
"autocrlf"问题是跨平台仓库的典型问题(即在Linux服务器上使用tortoisegit的samba共享)。我意识到,有时(经常)它更像是一个"chmod"问题而不是一个autocrlf问题: - git状态窗口显示待处理修改 - git状态Linux不显示任何内容 "mode change 100755 => 100644 config/packager.xml" 请检查您的"静态"文件是否没有+x属性(如果是这种情况,tortoisegit将无法正常工作)。"

确认,我也在Windows上使用cygwin Git时遇到过这个问题。 - Amedee Van Gasse

0

虽然我不知道是什么导致了这种奇怪的行为,但我知道另一种可能有效的丢弃更改的方法。

警告!务必非常小心并先备份;这可能会造成极大的破坏。

如果您关心的所有数据都已提交到存储库中,您可以简单地删除工作目录中的所有内容(当然除了隐藏的 .git 目录),并运行 git reset --hard HEAD,以便 Git 仅从存储库数据重新创建工作目录。

在执行此操作之前,请仔细检查是否有任何重要数据未被 Git 跟踪。仅检查未提交的更改状态 git status 是不够的 - 请记住,删除工作目录中的所有文件也将删除您告诉 Git 忽略的文件,并且它们不会因为根本没有被跟踪而无法使用 git reset --hard HEAD 重新创建。


除非存在未跟踪的文件,否则为什么这会产生任何影响,而不是一个git reset --hard呢? - djechlin
@djechlin 因为Git没有跟踪已经签出的文件曾经具有不同的行尾符设置。在几个安装中观察到这种情况,其中对现有文件进行了 core.eol 和 core.autocrlf 设置的更改。如果Git认为它不需要,git reset --hard 将不起作用。 - eis
这个建议对我没用。删除了所有内容,执行了 git reset --hard HEAD,但仍然看到文件被修改了。 - James Moore

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