git是否真的需要.gitattributes文件?

11
最近我在研究.gitattributes,还发现了像这样的地方https://github.com/alexkaratarakis/gitattributes,他们尝试为所有文件类型维护gitattributes。然而,在我的想法中,浏览那些文件时,我本能地认为这是一个不可维护的混乱。这意味着你必须每次使用任何新文件扩展名或任何软件带出新文件扩展名时,都需要更新该文件,这是不可能做到的。当你和30多人的团队一起工作时,维护这样的文件只会是个噩梦,我们几乎无法维护一个简单的icons.svg文件。
但是,我已经编码并使用git多年了,涉及许多不同的项目,我从未使用过.gitattributes。我们在项目中使用像prettier这样的东西,它将换行符重写为“lf”,而且我们有在Windows上的开发人员等等,这种情况从来没有引起任何问题,VSCode也从来没有出现过像这样的问题。Git也会自动拾取二进制文件,如png,并自动显示像svg这样的文本差异文件,我从来没有配置过那些东西。
所以我问一个问题,真的有必要有这个文件吗?因为在我看来,这是签署了一个完全不必要的维护量,并且git足够聪明以找出如何处理文件和不应该处理的文件。

1
如果您使用像Linux或macOS这样的合理系统,您根本不需要任何东西:Git不会干扰文件,您也不会让它干扰文件。只有在用户A到M使用macOS,用户N到Z使用Windows时,才使用.gitattributes,以便Git干扰文件。 - torek
2
信任Git的最大问题是Git对“什么是二进制文件”和“什么是文本文件”的解释在某些(困难)情况下根本行不通。如果它一直在为您工作,那很好,但最终您会遇到其中一个无法正常工作。 - torek
2
我不能代表所有在“.gitattributes”中的内容,但它可以帮助避免人们推送具有重复内容但不同行尾(CR + LF vs仅LF)的文件。这可以防止很多麻烦。 - Jonathon S.
你有注意到Windows开发使用Git吗?我很确定他们有超过30个人在开发。你有一些具体的证据吗?我认为你找到的链接是一个已经接受了“让每一个小步骤都显式化”的观点,但还没有注意到陷阱或钩子的人。 - jthill
1
答案中尚未提到的另一件事是diff属性,它允许做一些有用的事情,比如查看代码库中特定函数的历史记录。 - philb
显示剩余3条评论
2个回答

10
真的有必要有这个文件吗?
是的,对于与Git相关的任何设置(如eol、diff、merge filters、content filters等),您希望任何合作者都遵循存储库。
这与git config不同,后者出于安全原因仍然是本地的(因为它可能包含敏感信息或危险指令)。
.gitattributes是您版本化的源代码的一部分,并有助于建立共同的Git标准。 例如,我总是放置(如VonC/gitcred/.gitattributes):
*.bat   text eol=crlf
*.go    text eol=lf

因为无论你的IDE/编辑器如何配置,我需要CRLF来正确运行我的Windows批处理脚本,而我更喜欢在Windows或Linux上编辑的Go文件使用LF。我一直认为像core.autocrlf这样的本地设置是一个反模式,最好将其设置为false。
但是.gitattributes可以声明许多其他的Git元素: .gitattributes文件并非“强制性”的,但它是Git工具箱中一个非常有用的工具,可以在项目代码库中安全地共享使用。
而且你甚至可以在裸仓库中阅读它:
从Git 2.43(2023年第四季度)开始,属性子系统学会了尊重attr.tree配置,该配置指定了从哪个树中读取.gitattributes文件。
查看提交 9f9c40c提交 2386535(2023年10月13日)由John Cai(john-cai
(由Junio C Hamano -- gitster --合并于提交 26dd307,2023年10月30日) attr:在裸仓库中从 HEAD 读取属性 Signed-off-by: John Cai 44451a2(attr: teach,2023-05-06,Git v2.41.0-rc1 -- merge)(attr: teach "--attr-source=" global option to "git",2023-05-06)的动机是为了使得在裸仓库中能够使用gitattributes更加方便。
然而,为了在裸仓库中更容易阅读gitattributes,我们将HEAD:.gitattributes设为默认值。
这与mailmap的工作方式一致,8c473ce("mailmap: default mailmap.blob in bare repositories",2012-12-13,Git v1.8.2-rc0 -- merge)。
而且,仍然使用Git 2.43(2023年第四季度):
请参见提交9f9c40c提交2386535(2023年10月13日),由John Cai(john-cai提交。
(由Junio C Hamano -- gitster --提交26dd307中合并,2023年10月30日) attr:添加attr.tree以设置从中读取属性的树状结构 签名:John Cai 44451a2 (attr: teach, 2023-05-06, Git v2.41.0-rc1 -- merge) (attr: teach "--attr-source=" global option to "git", 2023-05-06) 提供了将树状物作为属性源的能力。然而,在像GitLab这样作为裸仓库提供Git存储库的上下文中,通过设置一次即可将--attr-source指向HEAD,这样做会更容易。
添加一个名为attr.tree的新配置项,以实现此功能。

git config现在在其man page中包含以下内容:

attr.tree

一个指向仓库中的树对象的引用,用于读取属性,而不是工作树中的.gitattributes文件。

在一个裸仓库中,默认为HEAD:.gitattributes

如果该值无法解析为有效的树对象,则使用空树代替。
当使用GIT_ATTR_SOURCE环境变量或--attr-source命令行选项时,此配置变量无效。


1
非常感谢,这是非常有用的信息! - user16435030

3
这取决于具体情况。 .gitattributes 文件最常见的用途是处理行尾、工作树编码和 Git LFS。如果你使用 Git LFS,则需要将这些文件处理为 LFS 文件。
否则,如果你只关心行尾,那就要看你所使用的平台了。如果你的项目仅在 Unix 上使用,则不需要该文件。但是,如果你的项目可能会在多个系统上使用,则通常有一个这样的文件会很有帮助,以指示哪些文件是文本(即应进行行末转换),哪些不是。Git 经常能够猜测正确,但它只查看文件开头,在许多情况下,某些文件类型(特别是 PDF)以大块 ASCII 兼容文本开头,然后包含二进制数据,此时 Git 需要帮助。
如果你想包括像 shell 脚本或批处理文件之类的内容,那么你绝对需要一个 .gitattributes 文件,因为 POSIX shell 不接受 CR 作为行尾的一部分,而批处理文件必须包含 CRLF。因此,需要使用 eol=lfeol=crlf 来实现可重复的行为。
同样,一些 Windows 用户使用的工具仍然需要使用小端 UTF-16 和 BOM 存储数据。针对这些程序,通常需要使用工作树编码,以便 Git 将它们内部存储为 UTF-8 文本,并可以对它们进行差异和合并。现在大多数编辑器和工具都可以很好地处理 UTF-8 和 LF,这可能是你没有遇到问题的原因。
我强烈建议至少使用一个简单的 * text=auto,如果你的项目将在 Windows 上使用,这意味着人们不会意外提交 CRLF 行尾符号的文本文件,同时人们在跨系统工作时也会有自己喜欢的行尾符号。这是一个简单的步骤,可以让你的项目体验更好。

1
非常感谢您的精彩回答。我认为如果 * text=auto 可以解决大部分的 CRLF 问题,那么至少是相当容易维护的。或者如果它只适用于非常特定的边缘情况文件(如 PDF),那就不是太糟糕了。然而,我发现的链接让我吓了一跳,因为那就太多了。您是否还建议将 git config --global core.autocrlf input* text=auto 结合使用,还是这是不必要的? - user16435030
1
我还发现了这个链接:https://dev59.com/zGMm5IYBdhLWcg3wIsbj#35474954,如果我理解正确的话,它告诉我git会自动保留和保持文件结尾。所以我唯一能想到的问题是,如果你在Windows上创建了一个.py脚本,然后在Linux上使用它,那么它将保留crlf并且会出错。`* text=auto`能解决这个问题吗? - user16435030
2
使用 * text=auto 可以解决这个问题。使用 .gitattributes 几乎总是比使用 core.autocrlf 更好,因为你不必依赖其他人正确设置它,所以我对人们如何设置它没有强烈的意见,这是一个选择问题。 - bk2204

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接