当公共存储库时,应该包含什么.gitignore文件? [英] What should contain .gitignore file when is a public repository?

查看:7
本文介绍了当公共存储库时,应该包含什么.gitignore文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在学习有关.gitignore文件的所有内容,但有一个问题我想解决。.gitignore应包含您要忽略的所有文件。因此,您应该忽略由操作系统、您正在使用的IDE生成的文件...我的问题出现在存储库在Github上时,人们可以克隆它并推送更改。这些人可以使用其他操作系统,也可以使用其他IDE。因此,gitignore应该忽略由这些其他操作系统和IDE生成的文件。

你应该怎么做?是否必须在gitignore中写入所有操作系统生成的和所有IDE生成的文件?

推荐答案

我想马上强调两个背景要点:

  1. 如果您拥有存储库,设置规则。你为迁就他人所做的任何事情都是出于普遍的友好。

  2. 动词忽略是...往好了说,这很棘手。我稍后会描述我的意思。重要的是,在.gitignore中列出文件并不会完全忽略,除非您对"忽略"一词有一个奇怪的个人定义。

也就是说,友好的方法是让存储库只忽略项目将生成的文件。然后,让个人忽略文件忽略系统将生成的文件。

让我们使用一个具体的例子。假设您有一个使用Python的项目,其中运行python foo.py会创建foo.pycfoo.pyo和/或__pycache__/*文件,这些文件都不应该提交。因此,您应该从:

开始
*.pyc
*.pyo
__pycache__/

在您的.gitignore中,因为使用您的项目的任何人--您、您的同事或其他任何人--最终都会得到这些特定于特定Python版本的Python"目标代码"文件,因此不应包括在内。

但假设您个人正在使用MacOS及其Finder。Finder程序创建名为.DS_Store的文件。因此,您很可能会添加以下内容:

.DS_Store

到您的.gitignore。这不是错误的,但它对任何使用Windows的人都没有任何好处。Windows人员需要忽略哪些文件?我不确定,我不用Windows。但是,Linux人员可能会忽略vim编辑器创建的.*.swp文件。

如果您将.DS_Store放在您自己的$HOME/.gitignore中,而Linux人员将.*.swp放在他们的$HOME/.gitignore中,那么所有人都会对您的项目有一个愉快的体验。此外,他们的项目没有列出.DS_Store,因为他们是从Linux开始的,所以您会有一个愉快的体验。

这就是大意:您的项目(存储库).gitignore应该列出在使用您的项目时将在工作树中找到的文件的名称或命名模式,但这不应该提交给项目。换句话说,它不是特定于操作系统的,而是特定于项目的。其他文件名模式-特定于操作系统、特定于编辑器、特定于IDE等等-可以包含在其他忽略文件中,因此不需要在项目的.gitignore文件中列出。将它们列出在项目文件中不一定会伤害,但如果每个人员对事情都很明智,也没有什么帮助。

不是实际答案一部分的次要背景(您可以在此处停止阅读!)

人们对Git的.gitignore文件感到困惑。(我做了,从StackOverflow上的数百个问题来看,几乎每个人都做了。)我认为很大一部分原因是误解了Git的存储模式。

关于Git的第一件事--可能是最重要的一件事--是Git不是关于文件的,也不是关于分支的。Git实际上是关于提交的。Git存储库的核心部分由两个数据库组成。大型数据库保存提交和支持提交所需的其他内部Git对象。

git clone复制的是Git提交和其他Git对象的这个大型数据库。还有第二个更小的名称数据库:分支机构名称、标记名等。此数据库对其他Git可见,因此可以由git clone复制,但通常不只是复制。相反,git clone读取较小数据库并修改它,完全丢弃一些名称并更改其他名称。因此,当您使用git clone时,您会得到一个大型数据库的副本(所有提交)和一个修改后的小型数据库副本。(我们不会太仔细地查看此处较小的文件,因为它不会影响.gitignore个文件。)

提交本身都具有唯一的散列ID。这些是又大又丑的字母和数字字符串,例如b994622632154fc3b17fb40a38819ad954a5fb88。Git存储库可以快速判断它是否具有与其他Git存储库相同的提交:发送Git的Git只列出散列ID。接收Git只检查:我是否具有该散列ID的提交?如果有,则接收Git已提交。它不需要再次获得它。如果不是,则接收Git需要获得该提交。

这意味着您的第一个git clone可能很慢:您可能需要获取许多MB的对象。然而,在此之后,更新克隆只是获得它们仍然需要的的任何新提交的问题。你的Git调用他们的Git,他们列出一些散列ID,你的Git知道要得到什么,他们的Git知道你拥有什么。或者,如果您有新的承诺要提供给他们,您的Git会调用他们的Git,向他们提供一些散列ID,他们可以说我已经有那个我没有那个,给我!

当然,还有比这更多的东西。接下来要知道的是,每次提交都会存储每个文件的完整快照。这些文件以一种特殊的、只读的、Git只读的冻结格式存储,其中的文件进行了重复数据消除。提交存储文件的事实是Git,它实际上只关心提交本身,是如何为我们存储文件的。冻结和消除重复的格式是存储库不会变得非常庞大的原因,即使每次提交都有每个文件的完整副本:大多数提交只会重复使用上次提交的文件,这意味着Git不必存储新的副本。

但是,如果提交中的文件是冻结的、仅Git格式的,而您的计算机上的其他程序无法使用,那么您将如何实际使用这些文件?答案是:您不会。也就是说,您不会使用这些文件。Git要做的是提取这些文件到某个地方。该"某处"是您的工作树工作树

这里值得一提的是,尽管我们不会更深入,但每次提交不仅存储冻结的快照,还存储一些额外的元数据。这主要是您在git log输出中看到的内容:例如,谁提交了、何时提交以及为什么提交。为什么部分取决于提交的人:这是日志消息。一条好的日志消息非常有价值。Git可以告诉您发生了什么:Git会将前一个或提交的快照与当前或提交的快照进行比较,对于每个不同的文件,Git将向您显示将父副本更改为子副本的方法。但Git无法告诉您为什么添加或删除了某一行。只有这样做的人才能说出为什么他们这样做。

这意味着您看到和使用的文件根本不在Git中

如果您运行过:

git clone https://github.com/git/git

并有一份Git副本,您可以查看Git的源代码:有MakefileREADME.md等等。但这些都是你电脑上的普通文件。它们不是提交中的文件。它们是Git通过从快照中提取提交的文件而创建的副本。这些副本位于您的工作树或工作树中。您可以使用文件查看器查看它们,在编辑器中打开它们,等等。但它们不在Git中。它们在您的工作树中,您可以随心所欲地使用它们。

Git将在您要求的任何时间将任何给定的提交提取到您的工作树中:

git checkout v2.21.0
例如,

将使用标记v2.21.0来查找特定的提交散列ID(确切地说,8104ec994ea3849a968b4667d072fedd1e688642)并将提交提取到您的工作树。(如果您的Git是2.23或更高版本,您可以使用git switch而不是git checkout:它们在这里做的事情完全相同。)此提取过程包括从您的工作树中删除您的文件,并根据您要切换到的提交创建新的文件。但所有这些文件都是您的文件,而不是Git的。

幸运的是,git checkout/git switch具有一些安全检查功能,可避免在您未保存所做的某些更改时删除文件。您可以将其关闭(例如,git checkout --force)或故意使用其他破坏性命令(git reset --hard)来擦除未保存的工作。在所有情况下,您基本上只是告诉Git擦除文件所做的内容,并从Git的文件中取回一些其他版本,例如保存在其他提交中的版本。

Git的索引临时区域

如果Git只使用两个东西--它的提交,其中一个是当前提交,以及您的工作树--那么git commit本身就很简单了。不幸的是,Git隐藏了第三个位置来保存每个文件。当您选择某个提交(通过git checkoutgit switch)作为当前提交时,Git不会将提交快照提取到您的工作树中。相反,它首先将提交快照提取到Git的索引中。

索引很复杂,有多种用途,但它的主要用途实际上很容易描述,而且您应该记住从这里开始:索引是您计划建立的下一个提交的地方。这就是它之所以被命名为临时区域的原因。索引保存每个文件的副本1,最初取自提交。你的工作树上也有一份副本。因此有三个活动副本:

  • 您可以使用git show HEAD:README.md看到的那个被冻结在提交中。
  • 您可以用git show :README.md看到的是在Git的索引中。它是冻结的格式,但与提交中的格式不同,它是可替换的。(这些文件有一半在Git中:准备提交,但尚未实际提交。)
  • 您实际可以使用的--在一个普通文件中--就是普通的README.md。这是您的,而且根本不在Git中。

当您运行git commit时,Git收集适当的元数据,冻结其索引中的所有文件然后,并使用这些文件作为新提交的新快照。

如果:README.mdHEAD:README.md匹配,则这两个文件是重复的,因此新的提交只是重用该文件。如果不是,可能它与其他提交和重复数据删除匹配,或者可能是全新的,并且实际上是真实存储的。无论如何,一旦你提交了它,它现在就冻结了,而且真的,完全在Git中。但是,如果您更改了工作树副本README.md,您可能希望Git冻结更新后的README.md这就是git add的用武之地。

<2-46]>命令告诉Git:使索引副本与我的工作树副本匹配。即,Git将从您的工作树复制(并压缩为冻结格式)更新的README.md文件,并将副本放入:README.md的索引中。因此,这就是为什么经常要求您git add文件的原因:每次您更改您的副本时,如果您希望Git更改其建议的下一次提交副本,则必须再次git add

当您稍后运行git commit时,Git将获取所有索引文件并将它们冻结为新的提交。因为索引副本都是冻结的格式,所以此过程可以而且通常确实会非常快。


1从技术上讲,索引包含的不是数据的实际副本,而是文件名、模式和Blob散列ID。除非您使用git ls-files --stagegit update-index直接开始挖掘索引,否则您无法真正区分它们。因此,可以将索引视为拥有文件的完整副本:Git很好地隐藏了BLOB对象技巧,因此您不需要关心。


这是.gitignore的用武之地

Git从其索引而不是从您的工作树进行新的提交。您的工作树是您的,可以随心所欲地处理。当您告诉Git覆盖它时,您只需要稍微小心一点,因为您的工作树中的文件都不是Git中(它们至多是旁边的Git的旁边)。但这也意味着您可以在工作树中创建您永远不希望Git存储到其任何提交中的文件。由于这些文件不在提交中,并且git clone只复制提交,因此这些文件不会出现在任何克隆中。

对于*.pyc*.ofromccc++这样的编译器输出文件,或者从Java编译器输出的文件或其他文件,这是一件好事:您通常不希望这些文件出现在任何克隆中。

但如果这些文件只是在您的工作树中闲置,则可能会出现两个问题:

  1. git status会不会向您唠叨
  2. 如果您使用集中git add everything操作,git add这些文件复制到Git的索引中作为新文件,现在,如果您git commit,它们将被提交。
.gitignore中列出文件名是防止这两种情况发生的一种方法。但这里有一个诀窍:如果文件已在Git的索引中,则将其列在.gitignore中没有任何效果。

Git索引中的文件称为跟踪跟踪的文件当前位于Git的索引中。未跟踪的文件位于您的工作树中,但当前不在Git的索引

请记住,您现在可以使用git add将全新的(To Git)文件放入Git的索引中。您还可以使用git rm将文件从Git的索引中完全删除。因此,索引的内容并不是固定的。Agit checkout填充索引,然后,您可以-也将-修改它:您将替换要在下一次提交中更新的任何文件。

当您运行git status时,status命令进行两个单独的比较。首先,它告诉您其他有用的东西,但我们将跳过这一点,转到两个比较:

  1. 两个比较中的第一个将当前提交HEAD与索引中的内容进行比较。对于每个完全匹配的文件,git status不会显示任何内容。如果有一些文件不匹配,或者是新的或丢失的,则git status表示为提交而暂存的更改并列出这些文件的名称。

  2. 第二个比较将索引与您的工作树进行比较。对于每个完全匹配的文件,git status不会显示任何内容。如果有些文件不匹配或丢失,git status将显示更改未暂存并列出这些文件的名称。

    /li>

这里的一个特例是未跟踪的文件:对于每个未跟踪的文件,git status列出文件的名称,2称这些未跟踪的文件。但如果您在.gitignore中列出这些名称,git status将关闭

请注意,跟踪的文件没有发生任何特殊情况。这些已经在Git的索引中了。它们包含在第一次比较中,Git会将索引副本与工作树副本进行比较,而不管文件是否列在.gitignore中。

因此,从这个意义上讲,这些.gitignore条目并不意味着忽略该文件。它们的意思是当文件未被跟踪时闭嘴。跟踪后,它们不起作用。

同时,git add.*(以及其他),用于对多个或所有文件执行集体添加操作。如果所有文件都包含未跟踪的文件,这些操作将非常不方便。因此,在.gitignore中列出文件名或模式会抑制整体添加操作。它甚至抑制了刻意的git add

$ touch foo.pyo
$ git add foo.pyo
The following paths are ignored by one of your .gitignore files:
foo.pyo
Use -f if you really want to add them.

所以.gitignore应该被称为.git-do-not-complain-about-these-untracked-files-and-do-not-automatically-add-them-when-using-en-masse-add-operations-or-even-explicit-requests,或者类似的名称。但谁愿意输入这样的名字呢?所以.gitignore就是这样。


2从技术上讲,每次需要git status -uallgit status -u时都会得到这个。否则,它有时会将物理存储在单个文件夹中的一堆文件组合在一起,并且只会不厌其烦地提到文件夹名称。

这篇关于当公共存储库时,应该包含什么.gitignore文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆