【已解决】git插件的文件更改(source control)显示错误

屏幕截图 2024-09-20 114523

git插件的文件更改窗口(source control)显示错误。

当我打开一个文件过一会关闭它,不做任何修改,此时source control页面会显示文件已经被修改。

且在刷新后,这个未被修改的文件依然保持显示。

如果我此时选择commit并push,不会发生任何事情,会显示no changes to commit

打开一个文件过一会关闭它,不做任何修改,此时source control页面会显示文件已经被修改

这如果排除了 自动 lint / 自动格式化类 插件的影响,
还有个可能是, 笔记被其他软件协同编辑, 混入了跟 Obsidian 风格不同的换行符

Obsidian 应该是永远用 “LF” 换行 (刚实测 Windows 里, 当 md 文本原先为 CRLF \r\n 换行时, 以 Ob 打开该笔记即使啥都不做直接关掉, 也会将 \r\n\n),
但保不准有些工具一定要写入 “CRLF” 换行

此时, 即使只在 Ob 里打开立即关闭, 也会被修改换行符, 于是此变化被 git 检测到

另一个类似的因素是, git 设置可能默认 “提交时自动转 LF; checkout 时要先看平台, 若为 Windows 则自动转 CRLF”, 如果 git 有拉取远程 repo 并 checkout 回本地的操作, 显然也将在 Ob 库内制造大量 CRLF 换行的文件, 这些文件一旦被 Ob 打开过, 就又陷入上述困境


如果确定是由于这个事, 可以考虑在 git 层面, 设法抹平差异就行

例如:

git config --global core.autocrlf input  
# 提交时在远端仓库转换为 LF, 检出到本地时不转换 (尊重远端仓库的数据), 
# 本地仓库现存的不一致, 由用户自行将现有换行符弄成统一

当然也有更激进些的设置


如果我此时选择commit并push,不会发生任何事情,会显示no changes to commit

这个还是得先看, 是否跟上述原因相关

1 个赞

非常感谢您的回答,您的意思大概是提出了一种可能:远端是LF换行,本地是CRLF换行,用obsidian打开后会转化为LF换行(因此打开后git显示文件更改),commit的时候由git自动转化,把所有CRLF转化为LF,LF也转化为LF(因此commit显示没有变化)

对于您提出的可能,我认为有两种验证方式:1.在obsidian显示文件更改的时候,进入仓库用git status查看文件是否真正修改,以此验证是否是obsidian打开文件后是否修改了换行。 2.用某些工具查看”远端文件“和”本地文件“以及”被ob打开的本地文件“的换行是CRLF还是LF。

我会在验证完结果后回复您,另外也烦请您看看我的理解是否出错了

您的见解非常正确。除下面的截图外我还用vscode查看了文件的换行,的确,ob打开过的文件变成了LF换行,没被ob打开过的文件都是CRLF换行。

请问有没有更简单的方式解决这个问题,比如我能否让仓库的远端保持LF,这样不就能使得远端和本地以及obsidian打开的本地文件,这三者都是LF了吗?

git应该可以设置成忽略换行转换,具体记不清了,可以去问问gpt

我的操作一,使得远端项目以后 clone 下来都是 LF

如果我在 .gitattributes 文件中加入如下的内容

# else
* text=auto
# text
*.md text eol=lf
# -text
*.svg -text
*.pdf -text

此时在一个新地方 clone 这个项目,我的新项目的所有 md 文件就都是 lf 了,无论 clone 时的 git config --local core.autocrlf 是怎么设置的。
如果我在一个都是 CRLF 的项目工程下加入这个文件,再使用 git add --renormalize .,没有任何效果。这个文件只对于 clone 有效,对于把本地文件改为 LF 无效

我的操作二,当前本地项目也从 CRLF 变为 LF

windows 和 linux 都把工作区设置成 git config --local core.autocrlf false
之后 git add --renormalize .
之后取消本地暂存的所有更改,之后 discard,此时就保证了本地都是 LF 了。github 云端本身就一直是 LF,因此本地和远端都是 LF 了。
为什么取消本地暂存的更改后,本地文件还是会保持 LF?因为本地文件一开始是 CRLF,normalize 后变成 LF,但 discard 这个过程中,由于配置的是 false,因此不会把 LF 转化为 CRLF。整个过程中,本地就实现了由 CRLF 变为 LF。
之所以取消本地暂存的所有更改,是为了防止许多 obsidian 忽略的文件夹的一些脚本文件从 CRLF 被修改为 LF,这些文件可能包含 css、svg 等,修改后再 push 到远端不确定是否会发生问题,不如就不修改远端了,只是把本地的所有文件改为 LF。

1 个赞

感谢楼主的研究! 我记录一下, 这些我以后也用得着

.gitattributes 这办法在某些场景看着也有用~