Git中Unity 文件无法回滚或始终显示未暂存文件问题排查指南
Git 中 Unity 文件无法回滚或始终显示未暂存文件问题排查指南
1. 问题现象
Unity 工程中偶尔会遇到:
- SourceTree 一直显示某个文件为 Modified.
- 点击恢复后仍然出现.
- 暂存、恢复反复无效.
- Diff 看不到实际内容变化.
git restore后git status仍然显示修改.
这种情况通常不是 SourceTree 本身的问题, 而是:
1
2
3
4
5
Git Index 中的文件状态
+
Working Tree 中的实际文件
+
.gitattributes 的规则
三者对文本/二进制或 CRLF/LF 的理解不一致.
2. 先按这个流程排查
假设异常文件为:
1
Path/File.meta
Step 1: 查看状态
1
git status --short
Step 2: 查看 EOL 和文件类型
1
git ls-files --eol -- "Path/File.meta"
常见结果:
1
2
3
i/lf w/lf attr/text eol=lf
i/crlf w/crlf attr/text eol=lf
i/-text w/-text attr/text=auto eol=lf
含义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
i/... Git Index 中保存的文件状态
常见值:
i/lf = Index 中使用 LF
i/crlf = Index 中使用 CRLF
i/-text = Git 将 Index 中的文件视为二进制
w/... Working Tree, 即本地磁盘上的实际文件状态
常见值:
w/lf = 本地文件使用 LF
w/crlf = 本地文件使用 CRLF
w/-text = Git 判断本地文件为二进制
attr/... 当前 .gitattributes 最终匹配到的规则
常见值:
attr/text eol=lf = 强制作为文本, 并要求使用 LF
attr/text=auto eol=lf = Git 自动判断文本/二进制, 文本使用 LF
attr/-text = 明确作为二进制处理
Step 3: 查看 .gitattributes 最终规则
1
git check-attr -a -- "Path/File.meta"
例如:
1
2
text: set
eol: lf
表示强制作为文本并使用 LF.
Step 4: 判断是不是只有换行符变化
未暂存:
1
git diff --ignore-space-at-eol -- "Path/File.meta"
已暂存:
1
git diff --cached --ignore-space-at-eol -- "Path/File.meta"
如果没有输出, 通常说明实际内容没有变化, 差异主要来自 EOL.
3. 根据结果处理
情况 A: Index 是 CRLF, 规则要求 LF
例如:
1
i/crlf w/crlf attr/text eol=lf
说明仓库历史中的文件还是 CRLF, 但当前规则已经要求 LF.
确认没有实际内容变化后:
1
2
git add --renormalize -- "Path/File.meta"
git status
再次检查:
1
git ls-files --eol -- "Path/File.meta"
理想状态应变成:
1
i/lf ...
确认后提交即可.
情况 B: Unity .asset 实际是 Binary, 却被强制当 Text
Unity .asset 不一定是 YAML 文本, Terrain 等资源可能包含二进制数据.
不建议:
*.asset text eol=lf
建议:
*.asset text=auto eol=lf
这样 Git 会自动判断:
1
2
YAML .asset -> Text -> LF
Binary .asset -> Binary -> 不做换行转换
修改 .gitattributes 后:
1
2
3
git add .gitattributes
git add --renormalize -- "Path/File.asset"
git status
再验证:
1
2
git check-attr -a -- "Path/File.asset"
git ls-files --eol -- "Path/File.asset"
二进制 .asset 的正常结果可能是:
1
i/-text w/-text attr/text=auto eol=lf
情况 C: 只是普通文件修改
如果 Diff 确实存在代码或 Unity 数据变化, 那么它不是 EOL 问题.
需要恢复时直接:
1
git restore --source=HEAD --staged --worktree -- "Path/File"
4. 修改 .gitattributes 后如何让旧文件生效
.gitattributes 改变以后, 已经被 Git 跟踪的文件不会自动全部重新应用新规则.
针对单个文件:
1
git add --renormalize -- "Path/File"
确认没有问题后再提交.
如果确认整个仓库都需要统一规则:
1
2
3
git add --renormalize .
git status
git diff --cached --stat
不要执行完直接提交.
如果突然出现大量图片、FBX 或其他二进制资源发生修改, 应先停止并重新检查 .gitattributes.
如果要确认暂存内容是否只有 EOL 变化:
1
git diff --cached --ignore-space-at-eol
没有输出通常说明没有实际文本内容变化.
5. Unity 推荐的关键 .gitattributes 规则
完整配置可以按照工程需要扩展, 这里重点保留 Unity 最容易出现问题的部分:
* text=auto
*.cs text eol=lf diff=csharp
*.shader text eol=lf
*.compute text eol=lf
*.cginc text eol=lf
*.hlsl text eol=lf
*.shadergraph text eol=lf
*.shadersubgraph text eol=lf
*.meta text eol=lf
*.unity text eol=lf
*.prefab text eol=lf
*.mat text eol=lf
# .asset 可能是 Text 或 Binary.
*.asset text=auto eol=lf
*.png binary
*.jpg binary
*.jpeg binary
*.dll binary
核心原则:
1
2
3
明确是文本的 Unity 文件 -> text eol=lf
可能是文本或二进制 -> text=auto
明确是二进制 -> binary
6. core.autocrlf
检查当前设置:
1
git config --show-origin --get core.autocrlf
如果仓库已经通过 .gitattributes 明确规定 eol=lf, 通常应优先以 .gitattributes 作为仓库统一规则.
必要时可以为当前仓库设置:
1
git config core.autocrlf false
但它更适合作为辅助配置, 不应该替代 .gitattributes.
7. 嵌套 Git 仓库需要额外注意
例如:
1
2
3
Repository A
└── Packages/
└── Repository B
如果 A 和 B 都在跟踪同一个物理文件, 那么这个文件实际上同时受到:
1
2
Repository A 的 Index / .gitattributes
Repository B 的 Index / .gitattributes
两套规则影响.
因此出现异常时应该分别进入两个仓库执行:
1
2
git ls-files --eol -- "文件"
git check-attr -a -- "文件"
有可能子仓库已经是 LF, 但父仓库历史 Index 仍然保存 CRLF.
此时应在真正出现问题的仓库中执行对应的 renormalize.
8. 不建议的处理方式
不要为了隐藏问题使用:
1
git update-index --assume-unchanged "文件"
也不要一开始就使用:
1
git reset --hard HEAD
更不要在大型旧工程中未经检查直接执行:
1
git add --renormalize .
正确顺序始终应该是:
1
2
3
4
5
6
7
8
9
10
11
12
13
定位异常文件
↓
检查 i / w / attr
↓
确认是否只有 EOL 差异
↓
修正 .gitattributes
↓
小范围 renormalize
↓
检查 Diff
↓
提交
9. 最常用命令
以后再次遇到”文件一直 Modified、恢复无效、Diff 又看不到变化”时, 优先执行:
1
2
3
4
git status --short
git ls-files --eol -- "文件"
git check-attr -a -- "文件"
git diff --ignore-space-at-eol -- "文件"
确认属于 EOL / Attribute 问题后:
1
git add --renormalize -- "文件"
最后再次验证:
1
2
git ls-files --eol -- "文件"
git status
重点记住:
1
2
3
i/... = Git Index
w/... = Working Tree
attr/... = .gitattributes
当这三者对文件类型或 EOL 的理解不一致时, 就容易出现 Unity 文件无法正常恢复、反复 Modified 等问题.