2

我在 Windows 10 上使用 GitHub Desktop。我想设置一个 git 存储库,其中将包含一些文本文件(.md 或 .adoc)和 Freemind 思维导图(.mm)。Freemind 使用基于 XML 的文件格式和 Unix 样式的换行符 (LF)。

在过去的 4 个小时里,我想我已经阅读了每个 StackOverflow 讨论和每个可以在网上找到的关于 EOL 规范化的 git 文档 - 它仍然让我发疯!许多讨论似乎已经过时,意见似乎相互矛盾。这是我到目前为止的情况:

  • 我已经离开core.autocrlfcore.safecrlf保持默认值
  • 正如推荐的那样,我正在使用一个.gitattributes文件* text=auto- 我对我的文本文件的自动转换很好。
  • 为了保留我添加的 .mm 文件的 LF*.mm text eol=LF

令我困惑的是这个警告:

> git add Mindmap.mm
warning: LF will be replaced by CRLF in Mindmap.mm.
The file will have its original line endings in your working directory.

据我了解,它* text=auto等同于core.autocrlf=true并确保所有 EOL 在提交时都转换为 LF - 所以在这种情况下是 LF->LF。并*.mm text eol=LF确保在结帐时保留 LF - LF-> LF 在另一个方向上也是如此。不涉及 CRLF!那么为什么 Git 会警告我某些转换会导致 CRLF 呢?

问题 1:当我在 GitHub 上公开我的项目时,我想确保不会遇到 UNIX 用户的跨平台问题。我的案例的最佳做法是什么?如果我一切正常,我可以忽略警告吗?

问题 2:在某些情况下,.mm 文件也可以包含 CRLF。当然,我可以将它们作为二进制文件处理,但我不会再看到 GitHub Desktop 中的任何差异。有没有办法仍然将它们视为文本文件,同时保留混合换行符(LF 和 CRLF)?

非常感谢任何提示!

4

2 回答 2

2

我不使用 Windows,因此有点犹豫提出建议,但我可以在这里描述各种机制,并至少提出一些。:-)

转换文件数据的操作,包括修改行结尾的任何操作,在数据从存储库提取到工作树时应用(通常 - 有一些特定的例外) - 这基本上是git checkout,但请参阅最后的注释-或添加到存储库中,基本上是git add.

为了转换文件数据,Git 必须知道哪些文件被转换哪些转换要应用。Git 必须对每个文件进行分类以决定要做什么。

有些文件显然是二进制文件,有些几乎可以肯定是文本,有些则相当模糊。Git 会猜测是否需要。你可以(我猜,也许,曾经不得不这样做?)通过设置or告诉它猜测,但请参阅下一段。core.autocrlf=truecore.autocrlf=input

如果你有一个.gitattributes文件,你可以根据文件的路径名告诉 Git 文件,例如,*.txt应该始终将其视为文本文件,而*.bin文件不应视为文本文件。这为您提供了更好的控制,因为您不仅可以根据这样的路径名进行匹配,还可以编写以下任何一种:

*.ex1   text      # definitely text
*.ex2   -text     # definitely not text
*.ex3   text=auto # please guess for me based on file contents
# don't mention *.ex4: check core.autocrlf to decide whether to guess

仅基于这部分,我建议core.autocrlf永远不要使用它,因为首先猜测似乎是可疑的。不过,至少text=auto你有一个明显的地方要求猜测。

独立于猜测或确定,您可以列出eol=crlfeol=lf在路径之后。git checkout这可以进行转换,即在决定是否在提取 ( ) 和插入 ( )时弄乱行尾时,文件被视为文本git add。在工作树中结束的是 CRLF 或 LF-only。在任何一种情况下,工作树中的 CRLF 在git add. 我怀疑,但没有测试,这不会影响git diff

(旧crlf-crlf、 和crlf=input设置无疑应该不再使用,但如果您确实使用它们,它们的行为将按照文档中的gitattributes描述进行。)

现在,您强调的一个明显问题是,使用-text将文件标记为“从不使用 autocrlf 或其他猜测转换”与 交互git diff,因为在产生差异之前git diff 还必须猜测文件是否为文本。gitattributes这里,我们可以回到文档,我们发现路径名可以有一个diff属性:

*.ex5   -text diff  # not text for crlf treatment, but text for diff
*.ex6   -text -diff # not text for either one
*.ex7   text -diff  # definitely text for crlf, but binary for diff
*.ex8   diff=my-diff-driver # use my diff driver; no opinion about text

完全省略diff会让 Git 猜测,就像它对 crlf 处理所做的那样。

请注意,路径名.gitattributes不必是模式:您可以列出:

path/to/some/file       -text
path/to/another/file    text

以防 Git 猜错某些文件。

我还没有提到core.safecrlf,但我认为文档中git config讨论在这里已经足够了。它由一系列在各种命令期间运行的特殊测试组成,提前在两个方向进行转换,最后的签出阶段转到一个临时文件,该文件立即被丢弃,只是为了查看工作树中的文件是否现在将保持他们现在的样子。也就是说,如果你现在做了,路径中的文件会改变内容吗?如果是这样,则转换不是“安全的”。git add path; git commit -m dummy; rm path; git checkout -- path

最后,我应该提几个特殊情况。文件从索引中出来的任何时候都会进行转换(行尾和涂抹过滤器);这包括命令git checkout-index。它们也可以在绕过索引的操作期间故意完成:git cat-file,通过添加--textconvor--path=--filters; git show, 和--textconv, 虽然细节会根据特定的 Git 版本而有所不同(其中许多选项不在旧版本的 Git 中)。类似地,转换(行尾和干净过滤器)在文件进入索引时随时完成,但也可以在git hash-object、 使用--path或中完成或抑制--no-filters

于 2017-02-21T01:49:50.413 回答
1

取消text设置.mm文件将阻止 gitcrlf对其进行转换,但它不会开始将它们视为二进制文件,因此 git-diff 和其他功能仍将正常运行。

在您的 .gitattributes 文件中:

* text=auto

*.mm -text

那应该可以解决您的第二个问题。然而,因为 git 不会强制.mm文件的行结尾,当你公开并且贡献者开始在 OS-X 和 Linux 上修改它们时,它可能会引起一些头痛。如果您可以描述行尾的规则,.mm则可以调整配置,或者提交挂钩可以帮助您执行它,除此之外,我不知道如何同时解决第一个和第二个问题。

于 2017-02-21T00:47:01.260 回答