Git换行符 - 无法存储,重置,现在无法在虚假的换行符提交上进行变基

42

我有一个仓库,我为它添加了一个 gitattributes,并且一直在正常工作。我通过 Dropbox 将其同步到另一台机器。当我在另一台机器上打开时,一堆文件突然出现在未暂存区中,并且显示为全部差异(所有的文件都有行尾差异),我的 crlf 结尾基本上是 .* text=auto,而我是在 Windows 上工作的。我尝试将更改藏起来、重置分支等等。最终,我决定提交这些文件,然后进行一些其他的提交,我想在行尾提交之前重新排序(并压缩)。但是当我尝试变基时,出现了:

error: Your local changes to the following files would be overwritten by merge
        # those same files
Please, commit your changes or stash them before you can merge.
Aborting
Could not apply 89b25b81fff1a1e7893319e123aaaca9c4162a95... <commit message>

当然,stash不起作用

这是一个bug吗?

相关:

编辑 与机器无关 - 在同一台机器上,某些(...)操作会使这些文件(它们在.gitattributes中作为文本)出现在“更改”部分。唯一似乎存在的解决方法是:

git rm --cached -r .
git reset --hard

请谨慎使用

编辑:上述的黑客攻击已被移至别名状态:

[alias]
     crlf = !git rm -r . --cached -q && git reset --hard

更新于2015年9月30日:我在一个NTFS分区中有一个git存储库,我在双启动环境下使用windows 7和arch linux。当我关闭Windows并启动Arch时,两个文件(html)显示为完全差异(行结尾差异)。上述解决方法不起作用 - 除非您多次应用它,在其中刷新gui...

我的.gitattributes

* text=auto

*.py text diff=python
*.html text
.project text
*.pkl -text

# M$ files
*.bat text eol=crlf

# UNIX files
**/generate_second_post text eol=lf

# git files - have them with LF, as I edit them via the shell (echo etc)
*.gitignore text eol=lf
*.gitattributes text eol=lf

NB: linux可以让我提交、切换分支,但无法让我变基(rebase) - 而且这些差异总是出现在gitk/git gui中。

2018/12/14转到了Mac,我的解决方法不再有效。我在git邮件列表中发布了一条消息:https://marc.info/?l=git&m=154482149623324&w=2

希望这会引起一些关注。

$ git --version
git version 2.19.2

2
你尝试过这个吗?git add -u .; git reset; - Attila Szeremi
1
@SzerémiAttila:你在我的场景中尝试过它并且它能正常工作吗?它应该做什么? - Mr_and_Mrs_D
1
将所有被跟踪的文件添加到索引中,然后使用索引将它们移除,保留文件中的所有更改。我之前在类似的情况下做过这件事,并让Git意识到实际上没有任何更改,从而消除了行尾问题。我之前已经回答过一个类似的问题,并给出了相同的答案:https://dev59.com/EmTWa4cB1Zd3GeqPE5qZ#11258263 - Attila Szeremi
如果我理解正确的话,您是通过Dropbox与Windows和Linux机器共享工作目录(即已检出的文件)?core.eol设置为什么? - Schwern
@Schwern:忘掉Dropbox吧,它并不总是运行。这是同一个物理文件夹,在NTFS分区(Windows分区)上,我在Linux上挂载。我的Windows git config --list 在这里:https://www.dropbox.com/s/fnyajvn6tz1s7wq/windows-config-all.txt?dl=0 - 我没有设置core.eol,但是core.autocrlf=false - Mr_and_Mrs_D
显示剩余4条评论
7个回答

30

经过5年的等待,终于有了完整的答案,感谢Torsten Bögershausen。

调试这个eol问题的方法是使用由Torsten Bögershausen添加的--eol switch to git ls-files进行调查。结果发现,相关文件是以CRLF格式被提交的,而后来添加的.gitattributes文件指定了这些文件的text属性。这会导致出现“非法状态”。旧的提交无法更改。

应该采取的措施是使用git add --renormalize .,使文件带有正确的(LF)行尾,并使用reset --hard命令将这些行尾还原到工作树中。

现在这对于旧的提交是没有帮助的(也就是那些处于这种非法状态的提交,在文件的错误行尾和gitattributes提交之间),检查这些提交可能会导致那些无法重置的更改。解决方法由@iKlsR提供的答案

$ cat .git/info/attributes
"Mopy/Docs/Bash Readme Template.html" -text
因为以下原因:

决定路径分配哪些属性时,Git会查询$GIT_DIR/info/attributes文件(该文件具有最高优先级),位于要查询路径的同一目录中的.gitattributes文件以及其父目录,直到工作树的顶层[]。

(强调我自己)

只需确保在重新规范化之后添加该行即可,否则文件将不会被添加到重新规范化提交中!


2
在运行重新归一化之后,我需要对所有受影响的克隆进行“行结束差异”的git reset --hard origin/master && git pull操作。 - gekkedev

4

这是我唯一的解决方案,我正在开发一个在Windows上的Linux仓库,遇到了CRLF和LF问题,无法重置文件。 - Sayyed Dawood

4
今天我们遇到了一个问题,似乎问题源于新添加的 .gitattributes 文件中的一些 CRLF 相关问题,其中有一行 * text=auto。当您重新基于或创建新分支时,该文件会跟随您并破坏之后的任何更改,并防止您在未先提交该文件的情况下离开该分支。
我们最初通过检出临时分支,将文件恢复到原始状态(修改前),提交,然后对整个分支进行回滚到最旧的提交,以使其看起来像主分支。这段时间有效,但之后又出现了类似的文件,同样的修复方法再次失败。
我们最终采用了与 op 在更新中分享的类似方法。在 .git/info/attributes 文件中有一行 file-to-remove -text 似乎可以缓解问题。我说缓解是因为我不确定是否会有任何负面影响,而且这只是针对一个文件的解决方案,如果有多个文件可能效果不佳。

2

以下是对@Mr_and_Mrs_D上面出色答案的改写:

git add --renormalize .  
git reset --hard   
git ls-files --eol | grep 'crlf' |  awk '{print $5 " -text"}' > .git/info/attributes  
git reset --hard  
git pull  
rm .git/info/attributes

我不确定两个重置是否都是必要的。此外,要小心git ls-files这一行——我让它过滤任何地方的crlf,因此这可能会选择具有crlf名称的文件;可能有更简洁的方法来做到这一点。如果您已经有一个.git/info/attributes文件,它也会截断该文件;如果需要,请使用>>进行修改,并在之后手动编辑文件以删除那些行。


2

你尝试过这个吗?

git add -u .
git reset

请考虑添加其余的评论以取悦评论者——他们是正确的,但您已经在您的评论中提供了他们需要的信息 ;) - Mr_and_Mrs_D
2
不行 - 没有起作用 - 仍然卡在 git rm --cached -r .; git reset --hard - Mr_and_Mrs_D

0

我也遇到了同样的问题,我使用的是Win7操作系统,sourceTree v3.0.9,git v1.9.5

在仓库根目录下,当.gitattribute文件中含有"text=auto"时,会显示许多本地文件行尾改变的更改,并阻止我做任何事情。 当我将text=crlf时,所有本地更改都消失了。

之前我尝试在配置文件中添加"[core] autocrlf = false",但没有帮助。

更新于12/06/2018:我的SourceTree使用的是旧版本的嵌入式git,只需在SourceTree中更新即可,现在在.gitattributes中使用"text=auto"一切正常。


Git 1.9.5?那是……(git tag -l --format="%(refname) %(taggerdate)" --sort="v:refname" v1.9.5)从2014年12月开始!?您能否检查使用Git 2.20-rc2是否仍存在此问题?(https://github.com/git-for-windows/git/releases) - VonC
@VonC,问题在受影响的存储库上使用git 2.19.0仍然存在 - 受影响的意思是曾经提交过带有行结尾的文件,这会使git感到困惑。 - Mr_and_Mrs_D
@Yang,这并没有真正修复任何问题-它只是告诉 git 提交 crlf 行结尾,这可能不是你想要的-是的,请更新 git :) - Mr_and_Mrs_D
@Mr_and_Mrs_D 注意,自Git 2.16(2018年第1季度)以来,您现在可以使用git add --renormalize来刷新有关.gitattributes规则的索引:https://dev59.com/fGw05IYBdhLWcg3wkivX#47580886 - VonC
@VonC,感谢您指出过时的git。 我使用SourceTree,并配置为使用嵌入式git,版本为v1.9.5。 我认为它是很久以前与旧版本的sourceTree一起安装的。我刚刚更新了SourceTree中的嵌入式git,并在.gitattribtues中设置了text=auto,现在我的问题已经解决了。 - Yang
@Yang 做得好,发现得很及时。你可以编辑你的答案,让你的解决方案更加明显。 - VonC

0

这些都在我的Windows 10 WSL上无法工作,我在README.md中有diff并且无法拉取更改,所以我从中进行了操作

echo README.md >> .gitignore # not sure if this is needed
rm README.md # this need to be rm without git
git pull
git checkout .gitignore # to remove the change

我认为如果你只是这样做,它也会起作用:

rm file
git checkout <branch>

但是我现在无法测试,因为我的代码库正在工作中。


将跟踪的文件添加到.gitignore中没有任何效果,因此可能不需要.gitigore行-README.md是否被跟踪? - Mr_and_Mrs_D
@Mr_and_Mrs_D 是的,它被追踪了,这就是我找到问题的主要原因。我已经删除了文件,但不确定 .gitignore 是否会影响 README 文件。 - jcubic
你在拉取上游的README时没有遇到冲突吗? - Mr_and_Mrs_D
@Mr_and_Mrs_D 我没有冲突,因为我不能拉取,git 告诉我先提交更改。 - jcubic
但是你执行了 git pull,对吧? - Mr_and_Mrs_D
@Mr_and_Mrs_D 我使用git pull从仓库中获取README.md文件(具有最新更改),因此git只重置该文件。在拉取更改之前,我删除了该文件,因此我的本地索引已清除(因为我在磁盘上没有任何更改),这样做可以将该文件重置为正确状态,这与克隆该存储库的效果相同。 - jcubic

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