Git分支切换后MSBuild删除Debug/Release目录下非项目引用文件的问题求助
问题场景梳理
先帮你把核心问题理清楚,方便大家聚焦分析:
- 你有一批手动放到Debug/Release目录的文件(配置、图片、测试数据等),这些文件不是项目编译生成的,VS正常编译时不会改动它们。
- 为了把这些文件纳入Git仓库,你在
defaultData分支新建了一个专门的项目,把这些文件加进去并设置为复制如果较新,再引用到主项目,这个分支上一切正常。 - 但切回
master分支(该分支没有那个专门项目,也未引用这些文件),编译主项目后,之前由defaultData分支复制到输出目录的那些文件会被自动删除;可如果是你手动用资源管理器复制的同一份文件,却不会被删,反复切换分支编译都会触发这个问题。 - 你开启了MSBuild的诊断日志也没找到删除相关的记录,之前也遇到过类似单文件莫名被删的情况,而且不想为所有测试文件都添加项目引用。
问题原因分析
这大概率是MSBuild的输出目录追踪清理机制在起作用:
- 当你在
defaultData分支构建时,MSBuild会把那个专门项目里的文件标记为「项目输出的一部分」,并在obj目录下的缓存文件(比如FileListAbsolute.txt这类)里记录这些文件的路径。 - 切换到
master分支后,项目文件发生变化(专门项目的引用被移除),MSBuild会重新生成输出文件的预期列表——这个列表里不再包含那些文件。 - 构建时,MSBuild会对比输出目录里的文件和预期列表,把不在列表里的「多余」文件删除。而你手动复制的文件,从来没被MSBuild标记为项目输出的一部分,不在它的追踪范围内,自然不会被清理。
至于诊断日志里找不到删除记录,可能是因为这个清理动作是MSBuild内部的Clean目标或其他辅助目标触发的,日志条目比较隐晦,没被你注意到。
解决思路
给你几个不同方向的解决方案,你可以根据需求选择:
把测试/临时文件移出输出目录(最推荐)
Debug/Release是MSBuild的专属输出目录,本身就设计为会被自动清理的空间,不适合存放非项目生成的文件。建议在项目根目录新建TestData、LocalAssets这类独立目录,把测试文件放在这里,然后在代码里通过相对路径读取该目录的文件。这样能完全避开MSBuild的清理机制,一劳永逸。禁用MSBuild的自动清理逻辑
如果一定要把文件放在输出目录,可以在主项目的.csproj文件里添加配置,关闭自动清理或跳过未引用文件的清理:<PropertyGroup> <!-- 完全禁用构建时的自动清理(会导致输出目录积累旧文件) --> <Clean>False</Clean> <!-- 或者只跳过清理未被项目引用的文件 --> <SkipCleanUnreferencedFiles>True</SkipCleanUnreferencedFiles> </PropertyGroup>注意:禁用清理后,输出目录会积累很多旧的构建产物,需要你定期手动清理。
给文件添加「排除清理」标记
在defaultData分支的专门项目里,给那些文件添加ExcludeFromClean属性,这样即使MSBuild追踪到这些文件,也不会把它们纳入清理范围:<Content Include="YourTargetFiles\**"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <ExcludeFromClean>True</ExcludeFromClean> </Content>这样切回
master分支后,MSBuild就不会把这些文件当作需要清理的「多余」文件了。分支切换后先清理obj目录
每次切换分支后,先手动删除主项目的obj目录(该目录存储MSBuild的缓存信息),再执行构建。这样MSBuild会重新生成输出文件列表,不会残留defaultData分支的追踪信息,也就不会误删文件了。
备注:内容来源于stack exchange,提问作者Pawcio

