Git checkout 失败,出现“非法字节序列”

ztyzrc3y  于 2023-02-02  发布在  Git
关注(0)|答案(3)|浏览(245)

我正在尝试将源代码回滚到git上的旧版本。

$ git checkout -f c258d300c8e85d68eeb15763eb14a059a2984f6d
fatal: cannot create directory at 'client-common/src/test/java/com/adi?caas': Illegal byte sequence

上述adi?caas是问题的原因。

git diff --name-only c258d300c8e85d68eeb15763eb14a059a2984f6d~ c258d300c8e85d68eeb15763eb14a059a2984f6d
client-common/src/test/java/com/adi<F0>caas/client/common/utils/MockConfigurationFileBuilder.java

这也可能是一个非标准字符adi<F0>cass。我如何克服这个问题?有没有办法自动Map这个字符到/。因为这是应该的,我有client-common/src/test/java/com/adi/caas/
我使用的是Mac OSX莫哈韦10.14.6和Git 2.16.2版本。

46scxncf

46scxncf1#

在macOS上,所有文件名都以UTF-8的特定规范化形式进行编码。无法创建名称不是有效UTF-8的文件,例如仅包含ASCII字符和0xF 0字节的文件名。
然而,在大多数Unix系统上,文件名是以任意的字节序列编码的,所以Git允许你用任意的非NUL字节序列命名文件。过去有人把一个非UTF-8的文件名放进你的仓库,现在这个版本号不能被 checkout 。
你将无法在macOS上 checkout 该版本。由于不区分大小写,Git会很乐意 checkout 重叠的文件,但如果无法创建目录,它将不允许 checkout 。如果你想 checkout 它,你可以尝试使用Linux VM或Docker容器。也可以使用git archive生成一个压缩包,然后使用归档工具将所需的压缩包解压缩到适当的目录中。您还可以在Linux系统上使用固定路径(使用git mv)创建该修订版本的副本,然后在Mac上将其检出。

mepcadol

mepcadol2#

看起来像是违反了(UTF-8)编码规则导致了原始问题。请尝试将LC_CTYPE设置为C,如下所示(这会导致字符串中的每个字节都是自己的字符,而不应用任何编码规则):

LC_CTYPE=C LANG=C git checkout -f c258d300c8e85d68eeb15763eb14a059a2984f6d

然后按照Java命名约定更正包名并提交,以避免将来出现类似问题。

xqnpmsa8

xqnpmsa83#

就像其他人回答的那样,创建文件的操作系统似乎允许使用你的操作系统不允许的文件名。当你 checkout 时,git试图创建一个非法名称的文件,然后它崩溃并退出。
以下是我使用的解决方案:我不需要包含非法字节序列的文件的文件夹中的任何内容(在您的例子中是client-common/src/test/java/com),所以我启用了git稀疏 checkout ,它允许您配置 checkout 时跳过的文件或目录列表。(注意:从技术上讲,您可以指定要选择进入的文件/文件夹,但我们会将其配置为检出除有问题的目录之外的所有内容)
在存储库根目录的shell中执行以下操作:

# first, turn on sparse checkout in the git config
git config core.sparseCheckout true

# check if the .git/info directory exists
ls .git/info

# if you got a "No such file or directory," create it. Otherwise, skip this step
mkdir .git/info

# save our avoid-directory in a variable to make the next line more readable
# (replace the stuff in quotes with your avoid-directory)
avoidDir="client-common/src/test/java/com"

# create the list of directories to ignore and add avoidDir
# (depending on your system, you may have to add a \ before the ! )
echo -e "/*\n!$avoidDir" >> .git/info/sparse-checkout

# now you can got checkout/reset/whatever and git won't attempt to create the file with the illegal name
git checkout -f c258d300c8e85d68eeb15763eb14a059a2984f6d

相关问题