今日、この問題に遭遇しました。私の場合、問題は、テキスト エディター (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/'
次に、 .gitattributesutf8-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 バイト シーケンスのプレースホルダーです。
# Remove 'abc' from beginning of file, if present
sed -b -e '1!b' -e 's/^abc//'
# Add 'abc' to beginning of file, if not present
sed -b -e '1!b' -e 's/\(^\|^abc\)/abc/'
UTF-8 BOM の場合、EF BB BF
「abc」の代わりにバイト シーケンスを使用します。
フィルターは、コマンドを実行してコミット時に BOM を削除し、clean
コマンドを実行してチェックアウト時に BOM を追加しsmudge
ます。これにより、作業ツリー ファイルに BOM が保持されますが、BOM が Git にコミットされたり、Perforce に送信されたりすることはなくなります。
( および の詳細については、gitattributesのドキュメントを参照してください。)clean
smudge
問題の診断
エラーメッセージは興味深いと思いました:
error: patch failed: path/to/file.csproj:1
error: path/to/file.csproj: patch does not apply
私のコミットがファイルの1行目を編集しなかったにもかかわらず、パッチは1行目で失敗したと言いました。
何が起こっているのかを見るために、私は走りまし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 操作が遅くなります。
ヒント
smudge
作業ツリーに BOM が必要ない場合は、フィルターの一部を削除できます。これにより、一部の Git 操作 ( などgit checkout
) が高速化されます。行を削除するsmudge
と、フィルター定義は次のようになります。
[filter "utf8-autobom"]
clean = sed -b -e '1!b' -e 's/^\\xEF\\xBB\\xBF//'