Git状态显示文件已更改,即使内容相同

331
我收到了别人的git checkout并试图将未暂存的更改提交到本地仓库。然而,即使内容完全相同,很多(如果不是全部)文件都显示为已修改
我已经将core.fileMode设置为false,并将core.autocrlf设置为false,但没有成功。
值得一提的是,我收到的Git仓库来自于使用Windows的人,而我使用Linux。 我该怎么做才能提交实际更改? 编辑:输出git config -l
user.name=Aron Rotteveel
user.email=<removed>
color.diff=auto
color.status=auto
color.branch=auto
color.interactive=auto
color.ui=true
color.pager=true
color.branch.current=yellow reverse
color.branch.local=yellow
color.branch.remote=green
color.diff.meta=yellow bold
color.diff.frag=magenta bold
color.diff.old=red bold
color.diff.new=green bold
color.status.added=yellow
color.status.changed=green
color.status.untracked=cyan
core.pager=less -FRSX
core.whitespace=fix,-indent-with-non-tab,trailing-space,cr-at-eol
alias.co=checkout
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
core.hidedotfiles=dotGitOnly
core.autocrlf=false
remote.origin.url=<removed>
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*

更新:添加了一些随机示例文件。这些文件只是纯文本,所以最容易包含。
原始文件位于此处:https://gist.github.com/c3c5302430935155ef3d。十六进制转储明确表明文件是不同的,但我不知道是什么原因造成的,也不知道如何解决。
头版本:
0000000: 4854 4d4c 2e53 6166 654f 626a 6563 740d  HTML.SafeObject.
0000010: 0a54 5950 453a 2062 6f6f 6c0d 0a56 4552  .TYPE: bool..VER
0000020: 5349 4f4e 3a20 332e 312e 310d 0a44 4546  SION: 3.1.1..DEF
0000030: 4155 4c54 3a20 6661 6c73 650d 0a2d 2d44  AULT: false..--D
0000040: 4553 4352 4950 5449 4f4e 2d2d 0d0a 3c70  ESCRIPTION--..<p
0000050: 3e0d 0a20 2020 2057 6865 7468 6572 206f  >..    Whether o
0000060: 7220 6e6f 7420 746f 2070 6572 6d69 7420  r not to permit 
0000070: 6f62 6a65 6374 2074 6167 7320 696e 2064  object tags in d
0000080: 6f63 756d 656e 7473 2c20 7769 7468 2061  ocuments, with a
0000090: 206e 756d 6265 7220 6f66 2065 7874 7261   number of extra
00000a0: 0d0a 2020 2020 7365 6375 7269 7479 2066  ..    security f
00000b0: 6561 7475 7265 7320 6164 6465 6420 746f  eatures added to
00000c0: 2070 7265 7665 6e74 2073 6372 6970 7420   prevent script 
00000d0: 6578 6563 7574 696f 6e2e 2054 6869 7320  execution. This 
00000e0: 6973 2073 696d 696c 6172 2074 6f0d 0a20  is similar to.. 
00000f0: 2020 2077 6861 7420 7765 6273 6974 6573     what websites
0000100: 206c 696b 6520 4d79 5370 6163 6520 646f   like MySpace do
0000110: 2074 6f20 6f62 6a65 6374 2074 6167 732e   to object tags.
0000120: 2020 596f 7520 7368 6f75 6c64 2061 6c73    You should als
0000130: 6f20 656e 6162 6c65 0d0a 2020 2020 254f  o enable..    %O
0000140: 7574 7075 742e 466c 6173 6843 6f6d 7061  utput.FlashCompa
0000150: 7420 696e 206f 7264 6572 2074 6f20 6765  t in order to ge
0000160: 6e65 7261 7465 2049 6e74 6572 6e65 7420  nerate Internet 
0000170: 4578 706c 6f72 6572 0d0a 2020 2020 636f  Explorer..    co
0000180: 6d70 6174 6962 696c 6974 7920 636f 6465  mpatibility code
0000190: 2066 6f72 2079 6f75 7220 6f62 6a65 6374   for your object
00001a0: 2074 6167 732e 0d0a 3c2f 703e 0d0a 2d2d   tags...</p>..--
00001b0: 2320 7669 6d3a 2065 7420 7377 3d34 2073  # vim: et sw=4 s
00001c0: 7473 3d34 0d0a                           ts=4..

拷贝版本:

0000000: 4854 4d4c 2e53 6166 654f 626a 6563 740a  HTML.SafeObject.
0000010: 5459 5045 3a20 626f 6f6c 0a56 4552 5349  TYPE: bool.VERSI
0000020: 4f4e 3a20 332e 312e 310a 4445 4641 554c  ON: 3.1.1.DEFAUL
0000030: 543a 2066 616c 7365 0a2d 2d44 4553 4352  T: false.--DESCR
0000040: 4950 5449 4f4e 2d2d 0a3c 703e 0a20 2020  IPTION--.<p>.   
0000050: 2057 6865 7468 6572 206f 7220 6e6f 7420   Whether or not 
0000060: 746f 2070 6572 6d69 7420 6f62 6a65 6374  to permit object
0000070: 2074 6167 7320 696e 2064 6f63 756d 656e   tags in documen
0000080: 7473 2c20 7769 7468 2061 206e 756d 6265  ts, with a numbe
0000090: 7220 6f66 2065 7874 7261 0a20 2020 2073  r of extra.    s
00000a0: 6563 7572 6974 7920 6665 6174 7572 6573  ecurity features
00000b0: 2061 6464 6564 2074 6f20 7072 6576 656e   added to preven
00000c0: 7420 7363 7269 7074 2065 7865 6375 7469  t script executi
00000d0: 6f6e 2e20 5468 6973 2069 7320 7369 6d69  on. This is simi
00000e0: 6c61 7220 746f 0a20 2020 2077 6861 7420  lar to.    what 
00000f0: 7765 6273 6974 6573 206c 696b 6520 4d79  websites like My
0000100: 5370 6163 6520 646f 2074 6f20 6f62 6a65  Space do to obje
0000110: 6374 2074 6167 732e 2020 596f 7520 7368  ct tags.  You sh
0000120: 6f75 6c64 2061 6c73 6f20 656e 6162 6c65  ould also enable
0000130: 0a20 2020 2025 4f75 7470 7574 2e46 6c61  .    %Output.Fla
0000140: 7368 436f 6d70 6174 2069 6e20 6f72 6465  shCompat in orde
0000150: 7220 746f 2067 656e 6572 6174 6520 496e  r to generate In
0000160: 7465 726e 6574 2045 7870 6c6f 7265 720a  ternet Explorer.
0000170: 2020 2020 636f 6d70 6174 6962 696c 6974      compatibilit
0000180: 7920 636f 6465 2066 6f72 2079 6f75 7220  y code for your 
0000190: 6f62 6a65 6374 2074 6167 732e 0a3c 2f70  object tags..</p
00001a0: 3e0a 2d2d 2320 7669 6d3a 2065 7420 7377  >.--# vim: et sw
00001b0: 3d34 2073 7473 3d34 0a                   =4 sts=4.

1
如果你的 core.filemode 没有设置或者设置为 true,输出结果会不同吗? - Mark Longair
另一个重要的信息是 git --version 的输出。 - Mark Longair
2
@AronRotteveel:很简单:第一个文件有CRLF行尾(Windows),第二个文件有LF(Unix)。 - sehe
7
git 2.8(2016年3月)推出了git ls-files --eol命令,可以快速查看EOL是否有影响。请参见下面的答案 - VonC
3
Windows用户可以运行git config --global core.autocrlf true来解决这个问题。 - Inyoka
显示剩余6条评论
26个回答

260
我已经使用以下步骤解决了这个问题:
  1. 从Git的索引中删除每个文件。

    git rm --cached -r .

  2. 重写Git索引以获取所有新行结尾符。

    git reset --hard

请注意,第2步可能会删除您的本地更改。 解决方案是在Git网站上描述的步骤的一部分。 https://help.github.com/articles/dealing-with-line-endings/

2
在我的情况下,我已经对一些文件做了一堆注释,然后将没有.git文件夹的repo复制到了新电脑上。当我意识到我缺少我的.git包时,回去检索它已经太晚了。所以我:
  1. 检出整个repo的新副本
  2. 用我的更改文件替换原始文件
  3. 运行OP帖子中的第一步:git rm --cached -r .
  4. 这样就可以暂存我的更改(和任何其他被替换的文件),因此我取消了暂存。此时我的repo恢复正常。
- cody
29
如果你这样做,就必须小心,因为你会丢失任何其他更改。 - Mohy Eldeen
我把我的仓库文件夹从Windows复制粘贴到Ubuntu后,遇到了这个问题。本地没有进行任何更改,但出于某种原因,git认为每个文件都发生了更改。这个解决方案解决了这个问题。 - Linek
1
对于那些使用Windows,但将其开发环境移植到Linux或WSL(这就是我来到这里的原因)的人来说,这是一个绝佳的解决方案。 - Joshua Schlichting
1
我认为在这种情况下使用git stash后跟git stash pop是一种非破坏性的解决方法。在我使用rsync同步机器上的目录时有效。 - vinnyjames
显示剩余4条评论

248

你改变了文件的模式吗? 在我的机器上,我将所有文件设为777,而本地开发机器却将它们设为755,这导致每个文件都显示为已修改。我运行了 git diff 命令,它显示旧模式和新模式不同。 如果这是问题所在,那么你可以轻松地忽略它们,方法是执行以下命令:git config core.filemode false


10
使用Windows 10的lxss(即Ubuntu Bash),在Windows文件系统中使用具有Linux中的git的存储库,我曾认为这是一个行结束问题。甚至没有考虑过文件模式也可能不同的情况。 - Matt L
@MattL 和 itsandy,我通常在 Win 10 上使用 Git Bash 进行开发,但今天我在 Mac 上发现 git 认为 .gitignore 文件已更改,实际上并没有。在这台 Mac 上,git config core.filemode 的响应是 true。我将其更改为 false,但没有帮助。 - Ryan
2
为什么默认情况下启用了 core.filemode?这可能会破坏许多干净的代码库历史记录。 - Martin Braun
1
我执行了 git config --system core.filemode false 来覆盖全局的设置。我并不在意,只要没有特别指定,这个设置就必须为false。 - Martin Braun
截至2022年11月20日,这对我起作用了。 - Nicholas Hansen-Feruch
显示剩余4条评论

75

更新:根据此问题的评论,问题已得到解决:

这很容易:第一个文件具有CRLF行尾(Windows),第二个文件具有LF(Unix)。 file工具(位于git\usr\bin中)将向您显示这一点(file a b将回复 类似于“a:ASCII文本,带有CRLF行终止符b:ASCII 文本”)

以下是原始答案:


你展示的差异没有显示单独的不同行。你可以发布.git/config(或更好的git config -l)。

您可能已经启用了一些空格忽略

您应该尝试禁用core.whitespace=fix,-indent-with-non-tab,trailing-space,cr-at-eol

还有

git show HEAD:myfile|md5sum
md5sum myfile

可以用来验证文件是否实际上不同。也可以使用外部差异工具。

git show HEAD:myfile > /tmp/myfile.HEAD

diff -u myfile /tmp/myfile.HEAD

# or if you prefer an interactive tool like e.g.:
vim -d myfile /tmp/myfile.HEAD

奇怪的是,这两个文件的md5sums不同,但我找不到任何空格差异。(我假设是这样,但我简单地没有看到它)。任何帮助都将受到欢迎。 - Aron Rotteveel
只需在某个地方上传一个示例(gist.github.com可能是适当的选择)。我假设它是在最后一行使用换行符,具有字节顺序标记或通常的非规范化UTF8编码。您还可以随时查看xxdbdiff以执行二进制差异。 - sehe
2
@AronRotteveel: 这很容易:第一个文件使用CRLF行尾(Windows),第二个使用LF(Unix)。编辑 使用file工具可以显示这一点(file a b将会回复类似于a: ASCII text, with CRLF line terminators b: ASCII text的信息)。 - sehe
1
在我的情况下,哈希值是相同的,但是Git仍然指示发生了更改。 - tofutim
@tofutim 模式改变了吗(权限?) - sehe
显示剩余4条评论

64

我遇到了同样的问题。在从Windows复制到Linux后,我发现所有文件都被修改了。 我使用fromdos来修复换行符,然后

git add -uv 

添加更改。它添加了3个文件(不是全部),我实际上修改了它们。在此之后,git status仅显示3个修改的文件。执行git commit后,一切都与git status正常。


3
谢谢,这正是我所需要的。我使用了@sehe的建议,比较md5sum以验证文件是否相同(在我的情况下是相同的)。之后,正确使用-u标志过滤那些没有实际差异的文件和有变化的文件。 - STW
谢谢,很有帮助。我在项目根目录下执行了 npm i 后遇到了这个问题。不知怎么的,许多文件的行结尾符都变成了不同的类型,导致了这个问题。 - Server Khalilov
这就是我期望的...已经做出的更改保留了下来,其余的都被撤销了。 - Deepak Ganachari
1
我曾经在同样的情况下苦苦挣扎。我使用了find . -print0 | xargs -0 dos2unix -ic0 | xargs -0 dos2unix -b命令将行尾符从Windows转换为Linux,并通过执行git add .来解决状态问题。之后,git status显示所有状态都已更新。看起来这是git的一个bug,不应该需要执行git add .来修复git status - Konard
谢谢,我刚刚使用了 git add -uv 命令,它立即生效了。 - 1cedsoda

58

在我的情况下,当我更改文件权限后,这些文件会被标记为已修改。

为了让git忽略权限更改,请按照以下步骤操作:

# For the current repository
git config core.filemode false   

# Globally
git config --global core.filemode false

4
你的回答节省了我很多时间。谢谢! - Pavel_K
1
完成此操作后,我建议将所需更改存储/暂存,重置/检出已更改权限的文件,然后重新启用 core.filemode。 :) - XtraSimplicity
2
我在将文件从一台笔记本电脑复制到另一台电脑后遇到了这个问题。你的修复解决了它。谢谢! - Sam

42

对我有用。我们的环境是混合的,有一些Mac和一些PC。 - PlunkettBoy
谢谢,这对我在从Windows切换到Linux后有所帮助。 - Al Cher

33
然而,很多(如果不是全部)文件即使内容完全相同也会显示为已修改。使用Git 2.8(2016年3月),您将能够快速检查这些更改是否与行尾相关。如果是这种情况,Devin G Rhode在评论中添加了:我通过向只有* text = auto的repo添加.gitattributes文件来解决了这个问题。

检查请参见提交a7630bd(2016年1月16日)由Torsten Bögershausen (tboegi)完成。
(由Junio C Hamano -- gitster --合并于提交05f1539,2016年2月3日)

ls-files:添加行尾诊断

When working in a cross-platform environment, a user may want to check if text files are stored normalized in the repository and if .gitattributes are set appropriately.

Make it possible to let Git show the line endings in the index and in the working tree and the effective text/eol attributes.

The end of line ("eolinfo") are shown like this:

"-text"        binary (or with bare CR) file
"none"         text file without any EOL
"lf"           text file with LF
"crlf"         text file with CRLF
"mixed"        text file with mixed line endings.

The effective text/eol attribute is one of these:

"", "-text", "text", "text=auto", "text eol=lf", "text eol=crlf"

git ls-files --eol gives an output like this:

i/none   w/none   attr/text=auto      t/t5100/empty
i/-text  w/-text  attr/-text          t/test-binary-2.png
i/lf     w/lf     attr/text eol=lf    t/t5100/rfc2047-info-0007
i/lf     w/crlf   attr/text eol=crlf  doit.bat
i/mixed  w/mixed  attr/               locale/XX.po

to show what eol convention is used in the data in the index ('i'), in the working tree ('w'), and what attribute is in effect, for each path that is shown.


3
虽然这展示了问题,但并没有解决它。 - Greeso
这为我的情况提供了最好的线索。我有一个被修改过的gradlew.bat文件,无论我如何重置工作目录(git reset --hard && git status和git reset --hard && rm gradlew.bat && git status && git checkout . && git status),该文件仍然保持修改状态。我有一个全局的.gitattributes文件,来自于这里:https://github.com/alexkaratarakis/gitattributes/blob/master/Web.gitattributes,还有一些额外的内容来自于这里:https://rehansaeed.com/gitattributes-best-practices/。 - Devin Rhode
git ls-files --eol 显示我的 gradlew.bat 是唯一一个没有设置 text=auto 的文件。在我的 ~/.gitattributes_global 中,我有 *.bat text eol=crlf,所以我尝试了 text eol=lf,但是没有起作用。然后我尝试在 .gitattributes_global 中使用 text=auto,这解决了问题。 - Devin Rhode
1
@DevinGRhode 干得好!ls-files --eol确实很方便。 - VonC
4
我通过在一个仓库中添加一个只有 * text=auto 的 .gitattributes 文件再次解决了这个问题 :) - 也许把这句话放在你的回答开头会更好? - Devin Rhode
2
@DevinGRhode 谢谢。我已经将您的评论包含在答案中以增加可见性。 - VonC

13

当我在Linux上克隆一个在Windows上创建的项目时,以下是我如何解决问题的方法:

为了使事情正常工作,您需要进行如下设置:core.autocrlf = input

以下是设置步骤:git config --global core.autocrlf input

然后再次从Github上克隆该项目。


1
这个方法适用于我在Windows上使用Visual Studio的情况,但是我会在WSL命令行中进行提交和其他检查。在命令行中,每个文件都显示为已更改,但在Visual Studio中,只有一些文件更改了。我在我的.gitconfig文件中添加了autocrlf = input,并立即解决了它。谢谢! - Big Data Brian
1
谢谢。我也从Windows转到了Linux。你的解决方案对我很有帮助。 - Noor Ahmed
如果您在Windows上使用VSCode和WSL,则这是解决方案! - codeananda

12

我只是将.git/config文件中的[core]部分设置为filemode = false,然后它就对我起作用了。

filemode = false

1
这个简单的解决方案对我很有效。谢谢。 - mohammad asghari
这个答案解释了为什么这样做。简而言之,这更像是文件系统中不一致的一种解决方法。考虑解决这种不一致性。 - isacvale

6

Git FAQ有一个可能相关的答案,尽管我以前从未遇到过这种情况:

为什么git diff有时会列出没有更改的文件?

git diff和其他git操作被优化,因此它甚至不会查看磁盘上和git索引中状态(大小、修改时间等)不同的文件。这使得对于小的更改,git diff非常快速。如果文件已经被某种方式触摸过,git diff必须查看其内容并进行比较,即使实际上没有更改,这也是一种更慢的操作。git diff列出这些文件作为提醒,说明它没有被最优化使用。运行git status不仅会显示状态,还会更新索引以显示未更改的文件状态,从而使得后续操作(不仅是diff)更加快速。导致diff列出许多文件的典型情况是运行批量编辑命令,例如perl -pi -e '...'。

git status对你来说显示了什么?


git status 简单地显示了修改部分中的大量文件列表。 - Aron Rotteveel
@Aron:根据那个线索,我会说:85%的可能是行尾转换。 - sehe
6
哇,这提醒了我们一些官方Git文档的晦涩难懂。 - Mars

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