文件名中的变音符号导致Subversion和git(MacOS)之间存在差异

时间:2019-03-05 09:32:42

标签: git svn coexistence

我的文件名带有变音符号(即Exposé.pdf)。

$ svn stat
!    Exposé.pdf
?    Exposé.pdf

我正在使用subversion和git彼此相邻(不是git-svn)。 我正在从Subversion迁移到git,并希望并存一段时间。 因此,我在多个设备上都有大型存储库。当我用git克隆一个仓库时,我将已经存在的subversion .svn文件夹添加到仓库中,我得到了subversion的差异(!项目丢失,?该项目不在vcs下),但文件名似乎完全相同,但是在罩他们不是! 我已经尝试过(请参见https://www.git-tower.com/help/mac/faq-and-tips/faq/unicode-filenames

git config --global core.precomposeunicode true 

但是没有任何区别。有任何线索吗?

1 个答案:

答案 0 :(得分:1)

“多个设备”可能是问题所在。确切的修复或解决方法可能不清楚。请参阅下面的技术详细信息。

通常,您不应该自己设置core.precomposeunicode,就像您不应该自己设置core.ignorecase一样。 1 这些设置以及core.symlnks是Git自己设置的 ,用于记录计算机的运行方式,在您运行{ {1}}或git init 2 如果您使用git clone进行了设置,我建议您从个人Git中删除该设置配置:

--global

全局取消设置此设置的原因是使用git config --global --unset core.precomposeunicode 设置会禁用新存储库中的自动检测功能。

启用自动感应后,您始终可以将现有存储库克隆到新副本。新克隆将具有针对当前本地条件的正确(本地)设置。除了--global以外,不得通过任何其他方式将此新克隆从一台计算机传输到另一台计算机。


1 这些可以用您喜欢的任意大写字母拼写。 Git文档使用camelCase来实现,分别称为git clonecore.precomposeUnicode。您可以 设置它们以用于特定的测试目的或用于您要处理以某种不良方式构建的存储库的怪异情况。但这等于对Git撒谎,所以要当心!在实验时本地(不是全局地)执行

2 这里还有另一种特殊情况。具有使文件名受到损害的这些“特征”的操作系统,以使您免受丑陋现实的名义,通常实际上是在每个文件系统的基础上执行此操作。例如,MacOS的大小写折叠功能在构建磁盘映像时可以更改。 Windows上的Symlink支持取决于Windows 的版本。因此,有可能完整地拾取Git存储库,将其移至其他文件系统,然后需要更改设置。这是将core.ignoreCase从一个文件系统迁移到另一个文件系统而不是使用git clonetarrar甚至zip来移动文件系统的明智选择。 Git存储库:克隆将正确设置设置,而非克隆复制操作则不会。


文件名是字节字符串,除非不是。

这里的根本问题是,Git希望相信文件名不过是具有两个或三个约束的字节串,Linux建立的 3 以及其他任何操作系统都没有建立的其他约束。这些字节字符串通常也应该是(但不是必须)有效的UTF-8序列。理想情况下,操作系统将让Git照原样使用这些字节字符串,而不会感到烦恼。

在Windows和MacOS上,这种理想立即立即变为现实。最明显和最直接的问题是,在Linux上,您可以创建一个名为cp -r的文件,然后创建另一个名为README不同文件,这两个文件将共存。在Windows和MacOS上,一旦您创建了这两个文件中的任何一个,就无法再创建 second 文件:任何尝试都只能重新使用第一个文件。

换句话说,Linux具有区分大小写的文件名,而Windows和MacOS没有。这意味着Linux用户可以自由创建readme README.txt文件并将 both 放入单个存储库中。克隆此存储库的Windows或MacOS用户无法同时使用这两个文件。

尽管如此,Windows或MacOS 上的Git用户仍可以使用这些文件。这样做很痛苦。我在对“Changes not staged for commit" even after git commit -am b/c origin has a file with de-capitalize filename的回答中展示了一种方法。同样的方法在这里也适用,但痛苦程度相同。

此规则也适用于某些Unicode文件名。特别是,Unicode具有多种拼写某些重音字符(如á,ü等)的方法。例如,如果我们有一个名为schön(漂亮)的文件,则可以使用字母序列将其拼写:

readme.txt

(每个都是一个Unicode 代码点),或者我们可以使用以下代码进行拼写:

s c h umlaut-o n

这些是个不同的字节码序列,因此,至少根据Git,它们应该是个不同的文件,即使这两个文件都会显示作为屏幕上的名称s c h o combining-umlaut n

MacOS说,这两个名称将显示相同,因此我不允许其中之一。如果您向操作系统提供“错误”的拼写,它将对其进行更正或拒绝。请注意,这与案例折叠情况有些不同:MacOS将允许您创建 schön readme,但不能同时创建。它将仅允许使用README的一种形式。

因为Git从 index 而不是从文件系统构建新提交,并且索引是普通数据文件,所以您可以放置所需的拼写,甚至两者都进入索引。这意味着您可以将一个或两个都放入新的提交中。 任何现有提交均具有现有拼写,并且无法更改。

加载现有提交(通过schön)会将提交的拼写复制到索引中,并保持原样。 git checkout设置告诉Git当Git尝试从复制文件时,操作系统是否以及如何修改文件的名称。将索引到工作树。然后,Git可以尝试撤消任何损坏(如果适用)。但是,并非所有情况都可以处理,尤其是文件使用两种拼写形式提交的情况,就像自述文件与自述文件中的案例折叠一样。

(另请参阅t/t3910-mac-os-precompose.sh中的Git对MacOS precompose-unicode的内部自测试。)


3 约束是:

  • 没有字符串以斜杠开头或结尾(对于Git不会存储目录的事实,后者是微不足道的;对于前者,如果存在,则不使用前导斜杠来解决);
  • 没有字符串连续有两个斜杠;和
  • 没有字符串具有嵌入的NUL字节(此规则来自编写Git的C语言,并且这些操作系统支持 ,所以这并不是真正的问题)。

斜杠规则是因为Linux将斜杠视为目录/子目录或目录/文件名分隔符。当然,MacOS的功能完全相同,尽管内部使用反斜杠,但Windows的大多数界面都支持此功能。因此,所有三个系统都对斜杠限制感到满意。但是,某些Windows文件系统也在内部使用UTF-16-LE,这在称为“代理转义符”的位置周围创建了一个额外的雷区。我不知道Windows如何处理这些问题。理想情况下,雷区不会从内部接口泄漏到外部接口,但是理想情况下,Windows将使用正斜杠和UTF-8。 :-)