忽略目录与忽略带通配符的目录

时间:2017-11-13 17:08:09

标签: git gitignore

我正在开发一个需要忽略某些目录的项目。是否有区别:

path/to/mydir/*

和此:

path/to/mydir/

我理解它的方式是上部路径忽略mydir中的所有文件,包括子目录的内容,而非wildstar示例忽略所有顶级文件而不包括子目录中的文件。

这是一种正确的思考方式吗?我什么时候想要使用另一个?我想一劳永逸地解决这个困惑。

提前致谢!

1 个答案:

答案 0 :(得分:1)

  

之间是否存在差异:

path/to/mydir/*
     

path/to/mydir/

是。 Git对.gitignore文件中的条目有一些有趣的(如特殊的)行为。当我们使用 un -ignore指令时,它们会开始出现,例如!path/to/mydir/file

  

我理解它的方式是上部路径忽略mydir中的所有文件,包括子目录的内容,而非wildstar示例忽略所有顶级文件而不包括子目录中的文件。

Unignore指令表明这不是很正确。特别是,如果忽略目录,则无法取消该目录中的文件。但是,如果忽略目录中的所有文件和子目录,则可以取消该目录中的文件(但不能取消其子目录,除非您明确取消忽略一个那些也是。)

  

我什么时候想要使用另一个?

如果您需要(无论出于何种原因),请使用path/to/mydir/* Git在状态检查和自动path/to/mydir期间打开目录git add并阅读其内容。如果您不忽略path/to/mydir下面的特定路径,则不会产生任何差异。

详细说明和背景

让我们从第一个特点开始,即使它不是这个问题的直接部分:.gitignore并不意味着忽略。这意味着更像:不要自动添加,尤其是不要抱怨,关于未跟踪的某些特定文件集。< / strong>但是,意味着,在某些情况下,甚至不会查看此目录。

Git不会在提交中存储目录。提交仅存储文件。当Git将提交提取到工作树中时,它将只是创建保存这些文件所需的任何目录。

任何现有提交中包含的文件都是固定的:不可更改和永久性(好吧,无论如何都是永久提交)。无论提交中是什么,然而这些文件都在其中,它们永远存在(直到提交本身被垃圾收集,如果有的话)。所以他们在.gitignore文件方面并不是很有趣。 .gitignore中的内容对他们没有影响:他们已经提交了。

进入提交的文件由运行git commit索引的内容决定。 1 此时,.gitignore文件的内容再次无关紧要:如果索引中有某些特定的路径名​​和blob-ID配对 - ,它会进入承诺。如果索引中的不是,则不会进入提交。

然后,这将我们定义未跟踪文件: 未跟踪文件是一个不在索引中的文件。只要您将git add个文件添加到索引中,就会对其进行跟踪,并且只要您git rm --cached索引中的文件,它就会被跟踪。请注意,这意味着跟踪文件集会发生变化! 未跟踪不是永久性的事情:它取决于索引现在中的内容。

通过&#34;而不是&#34;索引,它将是&#34;而不是&#34;提交。这实际上会使它被忽略。但是Git 抱怨嘿,这个文件没有跟踪!你不想现在添加吗?抱怨!呜咽!输入.gitignore:这为Git提供了一个文件列表,以便避免抱怨

文件的。目录怎么样?

嗯,Git实际上存储目录,如果你有一个空的目录并不重要。 Git不会抱怨并抱怨它,Git不会存储它。 Git只会存储文件。但所有文件都在目录中 2 如果我们只能列出目录,那将使我们的生活更轻松。所以我们可以。

如果这就是全部,那就不那么奇怪了。但这并不是故事的结局。 Git试图快速,并且要快速,避免实际查看正在存储的文件是非常重要的。文件系统操作通常很慢。因此,在Git用于跟踪文件的索引中,Git会保留一些关于这些文件的辅助信息,如果可以的话,它会使用它来避免查看它们。结果,Git实际上只打开并读取目录,如果它必须&#34;。

Git将打开并读取工作树的顶级目录,以找出它包含的文件和目录。对于每个文件,如果文件在索引中,则一切都很好:跟踪文件。如果索引中的文件不是,那么未跟踪,Git应该会抱怨。现在我们检查.gitignore文件以查找ignore和un-ignore指令。如果文件被忽略,而后来没有被忽略,Git会抱怨:

?? dir/file

(来自--short的{​​{1}}输出。)

对于目录,但是,该目录自动不在索引中。 3 可以被忽略,如果忽略,为什么呢,也许我们根本不必阅读它。那真的很快 - 这就是Git的作用。

如果目录被忽略,Git就不会打开并阅读它来查找更多文件。这意味着它不能找不到该目录中的任何文件,因此永远不会检查是否有任何文件被忽略而不是以后忽略

如果目录本身未被忽略,Git会打开并阅读它。然后它会逐个检查位于该目录中的每个文件和子目录,就像它对顶层一样(使用相同的代码递归)。因此,如果您忽略了git status,但dir/*随后 un - 已注册,并且dir/important存在,Git会发现它,并抱怨它未被跟踪,如果它& #39; sa文件,如果是目录,则读取其文件。

还有一点点

这涵盖了未跟踪的文件检测,但dir/important本身呢?我们可以运行:

git add

或:

git add .

或:

git add '*'    # quoted to keep the shell from expanding it

并让git add --all 执行目录扫描和git add。在这里,代码非常相似,除了不仅仅是抱怨未跟踪的文件,Git将自动git add(复制到索引中)任何已经跟踪的文件的更新内容 4 并首次添加任何未跟踪但未被忽略的文件。

同样,如果一个目录本身被忽略,Git就不会在里面查看它(虽然如果索引中已经存在被忽略目录中列出的文件,Git会检查它们是否应该删除,如脚注4)。另请注意,如果您git add,其中git add xyzzy是文件,且xyzzy当前未被跟踪且被忽略,则xyzzy默认会投诉并拒绝git add尝试你可以使用add来覆盖它:文件将进入索引,从而被跟踪,现在--force对它没有影响。

附注:路径名匹配

Git做glob style pathname matching.gitignore字符匹配文件或目录名称的任何部分,但不会跨越斜杠&#34;。使用斜杠结束glob模式会限制Git的匹配,以便它只匹配目录。因此:

*

告诉Git忽略所有内容(所有文件和目录),然后忽略 un -ignore目录。由于此时Git必须打开并读取目录,因此它必须将每个文件和目录名称传递给ignore-pattern-matcher,因此每个文件都将被忽略,并且每个目录都将被忽略 - 但是没有信任,所以Git然后会查看每个子目录。

1 由于$ cat .gitignore * !*/ 采用可以 文件添加到索引的标志和/或路径名参数,这只是一点点过度简化。我们可以通过在git commit进行提交时说出&#34;来解决这个问题。相反,为git commit留出空间来先修改索引。

2 从技术上讲,目录存储名称和文件 - 标识配对,而不是存储实际文件。详细信息因文件系统而异。

3 现代Git实际上可以,可选地,缓存有关索引中目录的数据,但这些特殊条目不应该影响其可观察行为。

4 请注意,这些已经跟踪过的文件的现有内容或之前的git commit内容已经在索引中。这只是用新内容替换它们。如果工作树文件已被删除,Git会注意到这种情况,并且也会删除文件的索引版本,即la add。要做到这一点,Git必须读取索引,并阅读有问题的目录 - 但是Git已经必须读取索引,看看这些文件是否未被跟踪。