請注意以下簡短場景(這是在 Powershell 中):
PS> git diff -U3 -r -M HEAD -- .\Metadata\LegacyTypeModules\xyz.Web.Main.draft.json | Out-File -Encoding ascii c:\temp\1.diff
PS> git apply --cached C:\temp\1.diff
error: patch failed: Metadata/LegacyTypeModules/xyz.Web.Main.draft.json:69
error: Metadata/LegacyTypeModules/xyz.Web.Main.draft.json: patch does not apply
這將失敗,因為檔案中的最后一行不以 CRLF 結尾:

但是,在 bash 中運行時,完全相同的命令可以作業:
$ git diff -U3 -r -M HEAD -- Metadata/LegacyTypeModules/xyz.Web.Main.draft.json > /c/Temp/2.diff
$ git apply --cached /c/Temp/2.diff
P11F70F@L-R910LPKW MINGW64 /c/xyz/tip (arch/1064933)
兩個補丁的區別在于:

所以這個問題似乎發生了,因為 Powershell 用 CRLF 終止了通過管道的每一行,而 bash 保留了原始的行尾。
我明白為什么會發生這種情況 - Powershell 對物件進行操作,并且物件是不包括EOL 字符的字串。寫入檔案時,Powershell 將物件轉換為字串(在字串的情況下,轉換為 nop)并使用默認的 EOL 序列來分隔行。
是否意味著在 EOL 敏感場景中根本無法使用 Powershell?
uj5u.com熱心網友回復:
的確:
PowerShell 總是將外部程式的輸出解碼為文本(使用
[Console]::OutputEncoding)然后,當線路可用時,它通過管道逐行發送解碼的輸出。
一個檔案輸出小命令諸如
Out-File然后總是使用平臺的本地行序列- CRLF在Windows -終止每個(字串化)輸入物件寫入目標檔案時(使用其默認的字符編碼(或通過指定的一個-Encoding),其在技??術上與用于解碼外部程式輸出的編碼無關)。
換句話說:PowerShell的管道(和重定向)并沒有支持傳遞原始二進制資料通過,因為PowerShell的7.2 -未來的原始資料的支持正在被討論GitHub的問題#1908。
解決方法:
使用 LF 換行符 (
"`n")手動連接和終止解碼的輸出行,并將生成的多行字串按原樣 (-NoNewLine) 寫入目標檔案,如zdan 的有用答案所示。在這種簡單的情況下,最容易委托給
cmd.exe /c,因為它cmd.exe的管道和重定向是原始位元組管道:
cmd /c @'
git diff -U3 -r -M HEAD -- .\Metadata\LegacyTypeModules\xyz.Web.Main.draft.json > c:\temp\1.diff
'@
請注意使用here-string以提高可讀性和易于嵌入的參考(此處不適用)。
uj5u.com熱心網友回復:
您可以嘗試使用joinunix EOL 替換 CRLF:
(git command arguments . . .) -join "`n" | out-file c:\temp\1.diff -NoNewline
uj5u.com熱心網友回復:
標準差異(也稱為補丁)以 LF 行結尾終止行。那是因為這就是 POSIX 為diff. 所有行都必須包含一個 LF 行結尾。
當 CR 在補丁中位于 LF 之前時,它被視為要補丁的內容的一部分。因此,您的情況中的補丁可能不適用,因為舊內容被列為具有 CRLF 行結尾,而事實并非如此。
不幸的是,PowerShell 在這方面完全被破壞了,它的管道破壞了通過它們的資料。對于任何型別的二進制資料尤其如此。如果您正在使用任何型別的工具,如 Git 等專為在 Unix 上運行而設計的工具,則需要避免使用 PowerShell 的管道。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/378106.html
