【问题标题】:Is it possible to commit a file that defies the line ending behavior specified by .gitattributes?是否可以提交一个违反 .gitattributes 指定的行结束行为的文件?
【发布时间】:2013-06-18 06:00:41
【问题描述】:

如果将.gitattributes 文件添加到给定目录,其内容完全如下:

*.txt    text

是否有任何可能的方式可以将新文件先前规范化的文件(例如所有 LF 行结尾)提交到该目录而不进行规范化?即,在启用.gitattributes 并指定text 模式后,有没有可能将新的CRLF 行结尾 引入存储库?

再次解释一下,.gitattributes 文件是一种绝对万无一失的方法来防止新的 CRLF 行被提交到包含 .gitattributes 文件的目录中的 *.txt 文件吗?我想说服我的同事.gitattributes 文件是完全足够的,而且排除 CRLF 的进一步措施(例如服务器端挂钩)是不必要的。

答案应该要么确认不可能覆盖.gitattributes 指定的行尾行为,要么提供一个反例解释如何绕过.gitattributes 文件并潜入某些CRLF 行尾。

【问题讨论】:

标签: git line-endings gitattributes


【解决方案1】:

不容易通过gitattributes,因为否定模式是被禁止的。

这天(2013 年 3 月)实际上有人向Make !pattern in .gitattributes non-fatal 提出了一个补丁。

因此,您只需将*.txt 之类的全局规则放在您知道不需要CRLF 的子目录中的.gitattributes 文件中。

并在.gitattributes 中保留更细粒度的text 规则,存在于具有混合内容的目录中。


kostmo提到in the commentsEGit bug 421364

在实现之前,我推荐这种设置:

  1. 对于每个 Eclipse 项目,转到 Properties > Resource 并将“New text file line delimiter”更改为 Other: Unix。提交生成的 .settings/org.eclipse.core.runtime.prefs 文件。
  2. 不要为 Git 配置任何 .gitattributes 或“core.autocrlf”。
    这意味着文件在工作目录中的行尾与存储库中的行尾相同。 Git 和 EGit 不会转换任何文件内容。

使用 1.,在 Eclipse 中创建的所有新文件都将具有正确的 (LF) 行结尾,即使是由 Windows 上的用户创建的。

对于已在您的存储库中使用CRLF 的文件,您可以修复它们并提交结果。我建议在命令行上使用dos2unixfromdos

注意:该问题 (bug 421364) 刚刚(2014 年 3 月 25 日)被Lars Vogel 重新认定为与bug 342372 重复。

所以,JGit 对.gitattributes 的支持是“指定的”,但它的实现仍在进行中

正在审核实施(2015 年 1 月):

解析和处理 .gitattributes 文件的核心类,包括支持读取 WorkingTreeIterator 和 dirCacheIterator 中的属性。

getAttributes 功能添加到tree walk。
属性的计算需要由TreeWalk 完成,因为它需要WorkingTreeIteratorDirCacheIterator


2018 年 8 月更新:上述错误 (bug 342372) 依赖于刚刚解决的 JGit bug 537410
"JGit rebase 和 stash 不保留行尾s"

问题在于processEntry() 期间的ResolveMerger 不记得文件的CheckoutMetadata(其中JGit 存储过滤器和eol 属性),然后在checkout() 中检出它们,忽略任何属性或过滤器.

ResolveMerger.cleanUp()也有同样的问题。

JGit commit 4027c5c(来自review 127290)应该可以解决这个问题。
感谢 Thomas Wolfactive contributor to JGit

这给 EGit 带来了希望:

EGit 通常将所有这些在暂存/合并/结帐中的 eol 处理留给 JGit。
EGit 唯一需要关心的地方是在比较框架中,当它必须自己读取索引条目时,它已经正确处理了CheckoutMetadata

【讨论】:

  • 好的,解释一下我的问题,上面的.gitattributes 文件是一种绝对万无一失 的方法来防止新的CRLF 行被提交到目录中的*.txt 文件包含.gitattributes 文件?我想说服我的同事 .gitattributes 文件就足够了,并且不需要进一步的措施来排除 CRLF(例如服务器端挂钩)。
  • @kostmo 是的,只要你保持配置core.autocrlffalse (stackoverflow.com/a/2016763/6309):你可以在.gitattributes 中定义eol 规则:见stackoverflow.com/a/12702862/6309跨度>
  • 你是说如果core.autocrlftrue,用户可以生成一个违反.gitattributes 设置的提交?
  • 不:gitattributes 规则优先于诸如 core.autocrlf 之类的全局配置:请参阅git-scm.com/docs/gitattributes:“core.eol 配置变量控制 Git 将在您的工作目录中用于规范化文件的行尾;默认是使用你的平台的本地行结尾,或者CRLF 如果设置了core.autocrlf。...如果text 属性未指定,Git 使用core.autocrlf 配置变量来确定文件是否应该被转换。”
  • 在将有问题的文件设置为.gitattributes 文件中的“文本”格式并规范所有这些文件的行尾之后,不知何故一些 CRLF 进入了我们的存储库。我怀疑 JGit/EGit(Eclipse 的内置 Git 客户端)没有遵守本地 Git 命令行客户端使用的相同规则。由于执行只是客户端,看来可以绕过.gitattributes归一化毕竟。
【解决方案2】:

再次解释一下,这个 .gitattributes 文件是绝对万无一失的方式

没有。 Git 提供了很多便利,可以让日常任务变得简单,并将减速带排除在有问题的事情上,但它不会限制您对自己的 repo 的控制。

我想说服我的同事,.gitattributes 文件完全足够,并且不需要进一步的措施来排除 CRLF(例如服务器端挂钩)。

它们是必要的。没有人可以控制其他人在自己的存储库中所做的事情。

git update-index --cacheinfo \
        100644,`git hash-object -w --no-filters path/to/file`,path/to/file

来自git hash-object docs

--无过滤器
按原样散列内容,忽略属性机制选择的任何输入过滤器,包括行尾转换。如果文件是从标准输入读取的,那么这总是隐含的,除非给出了 --path 选项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-05
    • 2012-05-03
    • 1970-01-01
    • 2017-04-28
    • 2014-03-23
    • 2019-02-04
    • 2012-05-08
    • 1970-01-01
    相关资源
    最近更新 更多