.gitignore 中的目标/ vs /目标/

Cod*_*ete 2 eclipse git egit

我正在使用 Eclipse(这可能无关紧要)并且我想从提交中排除 Maven 目标文件夹。

很多记号

  1. /target/**
  2. */target/*
  3. /target/**
  4. target/
  5. /target/

有什么不同?

它们每个的确切含义是什么?

tor*_*rek 7

TL;DR:你可能想要/target/.

让我们从工作树的明确定义开始(从gitglossary 开始,拼写为working tree):

实际签出文件的树。工作树通常包含HEAD提交树的内容,以及您所做但尚未提交的任何本地更改。

我们需要记住,Git 存储的以及与其他 Git 存储库交换的内容是commits。每次提交都会一直冻结一些文件集,以便在将来的任何时候,您都可以告诉 Git让我提交a123456...并在您提交时恢复所有文件a123456...。(每个提交都有一个独特的、又大又丑的哈希 ID,你会在git log输出和其他地方看到。)

提交与工作树

提交中的文件以特殊的、仅限 Git 的、压缩的、去重的和只读的形式存储。我喜欢称这些文件为freeze-dried。它们实际上无法更改。所以它们适合存档,但对于完成任何实际工作完全没有用。因此,Git 需要能够提取任何给定的提交,“再水化”冷冻干燥的文件并将它们转回您可以查看、使用和处理的普通日常文件。放置这些文件的地方是work-treeworking tree

工作树当然有一个顶级目录(或文件夹,如果你喜欢这个术语),你可以在其中存储各种文件,包括你的主.gitignore文件。该顶级目录可以有子目录(子文件夹),每个子文件夹也可以有自己的.gitignore文件。例如,当您询问/targetvs 时target,这很重要。

Gitignore 条目

.gitignore文件中的条目可以是以下任何一种形式:

  • name(没有像 那样的特殊字符*
  • name.*或者*.txt甚至name*txt
  • folder/
  • folder/*
  • folder/name
  • folder/name*txt 或任何这些变体
  • folder/subfolder/
  • folder/subfolder/*
  • 任何上述以斜线前缀,例如,/name/folder//folder/name
  • 以上任何一个,包括前缀有斜杠,然后也有前缀!,例如,!/folder/name

这并不是一个详尽的列表(您已经列出了其他几种形式),而是为了说明一些基本原则:

  1. 简单的文件名意味着具有此名称的任何文件或目录
  2. 带有斜杠后缀的名称表示具有此名称的任何目录(文件夹)。作为文件的实体与此类条目不匹配。
  3. 条目可以嵌入斜线 - 斜线不在前面,也不在后面,例如folder/name.
  4. 条目可以有前导斜线,例如/name/folder/,或者前导斜线嵌入的斜线,例如/folder/name
  5. 条目可以在不同的地方包含glob字符***, 。
  6. 条目可以带有前缀!

gitignore 条目的规则变得相当复杂,但一开始就足够简单了。请记住,它.gitignore可能位于您的工作树的顶级文件夹中,或位于某个子文件夹中!

  • 没有嵌入或前导斜杠的普通名称与该文件夹或其任何子文件夹中任何位置的任何文件或文件夹匹配。
  • 没有嵌入或前导斜线的斜线后缀名称与此文件夹或其任何子文件夹中的任何文件夹(但不是文件)匹配。
  • 如果一个项目有一个斜杠前缀一个嵌入式斜线任何一个就足够了,该条目匹配的唯一文件和/或文件夹,这个文件夹。因此folder/name/folder/name意思相同:匹配folder/name文件夹中命名的文件(或文件夹)- 即包含.gitignore文件的位置。不匹配文件sub/folder/name,例如。
  • 如果条目以斜杠结尾,则它仅匹配文件夹(不考虑其他任何内容)。

你说:

我想排除 Maven 目标文件夹

这需要回答一个子问题:这个 Maven 目标文件夹在哪里存在?是否只有一个这样的文件夹,或者target/子文件夹中可以有实体吗? (还有一个单独的问题,即.gitignore指令的意思并不完全是人们认为的意思,您需要注意index 中的内容,但我们将把它留到另一部分。)

如果这意味着:不要在target我的工作树的顶层包含任何内容,但请继续并包含例如已命名的文件,sub/target/file那么您应该使用:

/target/
Run Code Online (Sandbox Code Playgroud)

作为.gitignore工作树顶层中的完整规则。这有点多余,因为您已经知道这/target 一个文件夹,但它清楚地表示您要忽略在工作树顶层命名的文件夹target

如果这意味着:不要在 中包含任何内容build-artifacts/target/,那么您可以输入:

build-artifacts/target/
Run Code Online (Sandbox Code Playgroud)

或者:

/build-artifacts/target/
Run Code Online (Sandbox Code Playgroud)

进入顶层.gitignore或者你可以把:

/target/
Run Code Online (Sandbox Code Playgroud)

进入build-artifacts/.gitignore。inbuild-artifacts/.gitignore需要一个前导斜杠,因为/target/没有嵌入斜杠,而顶层.gitignore不需要前导斜杠,因为它有一个嵌入斜杠。

如果,在第三手(?第一脚),要求是忽略所有的文件任何其文件夹路径文件夹中包含一个target组件-例如,你不仅要忽略target/file,但也sub/target/file2sub/target/sub2/file3-那么你应该使用:

target/
Run Code Online (Sandbox Code Playgroud)

作为您的.gitignore条目,可能位于您的工作树的顶层。

索引/暂存区的作用

这些.gitignore文件与您的工作树中的内容有关,但 Git 不会您的工作树构建新的提交。相反,Git 从它调用的中间事物构建新的提交,不同的是,索引暂存区。(这两个术语指的是同一个实体。)

虽然指数有一些其他的角色,其主要原因之一,尤其是对于我们的目的,就在于它拥有每一个文件的副本,原来的承诺,你提取,或更新的副本或一个完全新的文件。也就是说,如果您提取的提交只有两个文件 filesfile1folder/file2,您的索引现在将包含file1和 的副本folder/file2

索引内的副本与提交内的副本采用相同的冻干格式。不同之处在于您可以替换索引中的副本——或添加到它们中,甚至将它们减去。也就是说,您可以运行git add file1以获取工作树中的有用版本file1,将其冷冻干燥,然后将其填充到索引中。你可以用 做同样的事情folder/file2,你可以像或一样放置文件。是什么呢,总之,是冷冻干燥工作树版本的文件,并将其塞进了指数。folder2/file3./file4git add

当您运行 时git commit,Git 只是简单地打包索引中的所有内容,然后从中进行新的提交。所以这就是为什么你必须一直git add归档:每次更改工作树副本时,都需要更新索引副本,否则 Git 不会保存新版本:Git 只会再次重新保存旧版本。(为了节省空间,保存旧文件的相同版本的提交实际上只是重新使用旧的冻干文件。他们可以这样做,因为这些文件是只读的。找到旧副本并重新安装总是安全的 -使用它,因为根据定义,Git 中的所有内容都一直处于冻结状态。只能更改索引和工作树副本!)

换句话说,您可以将索引视为建议的下一次提交。您将文件复制到其中以更新建议的下一次提交。要完全删除一个文件,所提出的下一个承诺,你可以使用git rm --cachedgit rm(无--cached):Git会从索引中删除该文件,可能从工作树太多了,现在你提出的下一个承诺只是没有那个文件全部。

文件可以位于索引/暂存区工作树中。这种情况一直发生。这样的文件称为tracked。内容并不一定要配合:这只是一个事实,即该文件是在索引中,现在,也是在工作树,这使得工作树文件跟踪。

如果一个文件被跟踪——如果它现在在索引中——那么你对 a 所做的任何事情都.gitignore不会影响它。要使其不被跟踪,您必须将其从索引中删除。

如果您从索引中删除文件——或者如果它现在已经不在索引中,因为它不在您之前检出的提交中——那么工作树副本是untracked现在.gitignore进入重要的。该.gitignore条目告诉 Git:

  • 不要抱怨这个文件。 通常,git status会向你抱怨,告诉你文件没有被跟踪,天哪,你不应该git add这样吗?这.gitignore让 Git 对那个文件闭嘴。

  • 不要自动添加这个文件。 如果你使用git add .orgit add *或类似的东西,你是在告诉 Git:添加所有内容。 将其.gitignore修改为:添加所有内容——除了这些也被忽略的未跟踪文件,不要添加那些!

  • 它具有第三个效果,即在某些(罕见的)情况下允许 Git破坏工作树文件,并改变git clean使用-x和的方式-X

真的,该文件不应该被称为.gitignore,而应该像.git-dont-whine-about-these-files-and-do-not-auto-add-them-either-and-maybe-occasionally-do-clobber-or-clean-them. 但是谁想一直输入呢?所以,.gitignore

结论

关于.gitignore条目还有更多需要了解,但这已经足够长(可能太长了)。摘要版本是:

  • .gitignore只影响未跟踪的文件;
  • 主要是关闭抱怨,避免自动添加;和
  • 使用尾部斜杠表示目录/文件夹(无论您喜欢哪个词),并使用前导斜杠表示目录中找到的内容。当您有复杂的条目(带有嵌入斜线)时,前导斜线是多余的,但可以传达您的意图。

如果您想要前导斜杠效果,但确实需要嵌入斜杠,则必须将忽略条目分发到子目录/子文件夹,或使用**符号(作为前导组件)来匹配任意数量的路径组件。否则几乎没有任何需要**

这里没有介绍:一旦 Git 意识到它不必读取工作树目录,它就不会费心去读取它。其结果是,忽略子目录通常使得它不可能取消忽略(与!规则)的任何范围内的子目录。