Git - 重命名带有非法字符的文件



我们的团队致力于存储库,该存储库包含一个目录,其中有管道字符为"|"的文件。我是 Windows 上唯一的一个,所以管道字符对于文件名是非法的。

  1. 当我进行"git pull"时,有没有办法将目录中的文件从 "2021|08|05" 重命名为"2021\08\05"?
  2. 当我进行"git push"时,有没有办法将目录中的文件从 "2021\08\05" 重命名为"2021|08|05"?
  1. No.
  2. 不。

这些是你问的问题的正确答案,但诀窍是,你问错了问题。 唉,正确问题的答案是:"是的,但这是一个可怕的解决方案"。 问题是:有没有办法解决存储在 Git 提交中的文件名中的错误/无效字符的问题?

在 Git 的早期,当它是一个只有少数人可以成功使用的 shell 脚本集合时,人们会用git fetch从其他地方获取新的提交,然后用git read-tree将这些提交读到 Git的索引中。

Git 的索引(Git 也调用暂存区域有时称为缓存)可以保存这些文件名。 事实上,即使在Windows上,Git的索引也可以保存名为aux.h的文件,Windows不会让你创建这些文件。 索引也没有文件夹:它只有名称带有嵌入(正)斜杠的文件,例如path/to/file。 Git 可以在其索引中保存两个不同的文件,一个名为README个,另一个名为readme。 不能有两个不同的文件,其名称仅在大小写上不同。

因此,Git 的索引/暂存区域可以很好地保存这些文件。 当您处理文件时,问题就来了。 Git 索引中的文件以特殊的仅限 Git 格式存储在那里,就像 Git 所说的blob 对象一样。 不能直接读取或写入 Blob 对象。 您必须使用更多的 Git 命令来执行此操作。 这非常不方便。

为了方便使用Git,我们通常不会使用所有单独的一步一步的内部 Git 操作:我们使用某种更高级别的、面向用户的命令,如git checkout。 我们签出整个提交:Git 将找到存储在该提交中的所有文件,将它们读入 Git 的索引,并将所有内部仅限 Git 的 blob 对象复制并展开为具有普通文件名的普通文件。

这一步——从 Git 的索引复制文件,使它们可用——是在 Windows 上出错的地方。 Git 索引中的文件名是path/to/2021|08|05。 Git 认识到path/to/必须在 Windows 上转换为两个文件夹pathpathto,以便 Git 可以在第二个文件夹中创建一个文件。不幸的是,Git 无法重新映射2021|08|05部分。该部分将保持2021|08|05,正如您所看到的,Git无法创建具有该名称的文件:操作系统只是说"不"。

此时,您可以做的是下拉到那些较低级别的命令。 您可以运行:

git rev-parse :path/to/2021|08|05

如果需要,也许会用引号,具体取决于您的外壳:

git rev-parse ":path/to/2021|08|05"

git rev-parse命令将显示文件的blob 哈希 ID。 然后,您可以使用以下命令访问文件的内容

git cat-file -p <hash>

将这些内容打印到标准输出。 如果您的 shell 支持重定向,则可以将输出重定向到名称由您选择的文件。 这使您可以查看和使用文件的内容。

git cat-file -p命令可以直接获取索引路径名,因此:

git cat-file -p ":path/to/2021|08|05" > path/to/2021-08-05

是一种将文件提取为可用名称的方法。

不幸的是,git add(您通常以这种方式更新文件)将坚持使用您在文件系统中为文件指定的名称。 同样,您必须依靠内部 Git管道命令来解决此问题。 例如,如果您需要更新该特定文件,您将:

  1. 运行git hash-object -w -t blob path/to/2021-08-05将更新后文件的数据转换为内部 Git 对象;
  2. 使用参数运行git update-index,使 Git 使用在步骤 1 中获取的哈希 ID 更新path/to/2021|08|05条目。

完成所有这些操作后,您可以返回到正常的 Git 命令,因为git commit从 Git 的索引/暂存区域中的内容进行新的提交。

这里的(相当大的)缺点是你不能使用很多正常的日常 Git 命令:

  1. git pull通常是不行的,因为它运行git rebasegit merge,两者都需要使用您的工作树(操作系统级文件)。 首先运行git fetch,然后根据需要执行尽可能多的手动工作。
  2. git checkout会失败:你可以使用它,但你必须手动对现在在 Git 索引中的每个错误文件名执行一些操作。
  3. git diff将显示差异,包括删除具有错误名称的文件,git status会将调整后的名称文件显示为未跟踪的文件(因为它们)。
  4. git add您需要对这些文件进行的任何更改也是不行的;请改用git hash-object -wgit update-index
  5. git rebasegit merge变得困难。 您可能可以按照步骤 2 和 4 处理它们,但这充其量是痛苦的。