今天我遇到了这个问题。在我的情况下,问题是由于我的文本编辑器(Visual Studio)会在它所触及的每个文件中添加一个Unicode BOM。同时,Perforce服务器被设置为从每个文件中剥离Unicode BOM,以防止Unicode BOM出现在Perforce中。这最终导致我的git p4 submit
提交失败,并显示以下消息:
error: patch failed: path/to/file.csproj:1
error: path/to/file.csproj: patch does not apply
最终解决方案
我在~/.gitconfig文件中添加了以下过滤器定义:
[filter "utf8-autobom"]
clean = sed -b -e '1!b' -e 's/^\\xEF\\xBB\\xBF//'
smudge = sed -b -e '1!b' -e 's/\\(^\\|^\\xEF\\xBB\\xBF\\)/\\xEF\\xBB\\xBF/'
然后我通过在 .gitattributes 文件中添加以下行来将 utf8-autobom
过滤器应用于有问题的文件:
*.csproj filter=utf8-autobom
然后我使用以下命令强制 Git 将过滤器应用于其索引:
rm .git/index
git reset
接着我将编辑过的文件提交到Git,并像往常一样将我的提交提交到Perforce:
git add .
git commit --amend
git p4 submit
工作原理
过滤器定义基于以下sed
命令,其中"abc"是适当的Unicode BOM字节序列的占位符:
sed -b -e '1!b' -e 's/^abc//'
sed -b -e '1!b' -e 's/\(^\|^abc\)/abc/'
对于UTF-8 BOM,我们使用字节序列EF BB BF
代替"abc"。
通过运行clean
命令,该过滤器在提交时移除BOM,并通过运行smudge
命令在检出时添加BOM。这将使BOM保留在工作树文件中,但防止BOM被提交到Git或提交给Perforce。
(有关clean
和smudge
的详细信息,请参见gitattributes文档。)
诊断问题
我认为错误消息很有意思:
error: patch failed: path/to/file.csproj:1
error: path/to/file.csproj: patch does not apply
即使我的提交没有编辑文件的第一行,但它说补丁在第一行失败了。
为了看清发生了什么,我运行了git diff p4/master HEAD
。差异显示,我的提交在文件开头添加了一个奇怪的<U+FEFF>
字符。我怀疑这与文件编码有关,因此我使用Notepad++打开了Git工作树中的文件。然后我在Perforce工作区中打开了相应的文件。Notepad++ 在 Git 工作树中显示编码为"UTF-8-BOM",而在 Perforce 工作区中则是 "UTF-8"。(Linux 和 Cygwin 用户:使用file <path-to-file>
命令显示文件编码信息。)
通过谷歌搜索“UTF-8-BOM”,我找到了正确的解决方法。
注意
安装此过滤器后,某些 Git 操作将变慢。
提示
如果您不需要工作树中的 BOM,则可以删除过滤器中的smudge
部分。这将加快某些 Git 操作(例如git checkout
)。删除smudge
行后,过滤器定义如下:
[filter "utf8-autobom"]
clean = sed -b -e '1!b' -e 's/^\\xEF\\xBB\\xBF//'