我正在开发一个需要忽略某些目录的项目。是否有区别:
path/to/mydir/*
和此:
path/to/mydir/
我理解它的方式是上部路径忽略mydir中的所有文件,包括子目录的内容,而非wildstar示例忽略所有顶级文件而不包括子目录中的文件。
这是一种正确的思考方式吗?我什么时候想要使用另一个?我想一劳永逸地解决这个困惑。
提前致谢!
答案 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已经必须读取索引,看看这些文件是否未被跟踪。