.DS_Store 文件在 .gitignore 中,但它不断弹出状态
.DS_Store file is in .gitignore, but it keeps popping up in status
我搜索了..我阅读了我可以在这里找到的关于相似甚至相同问题的所有答案。我看了教程。当它发生在某人的终端上时,它看起来超级简单和合乎逻辑。在我的,它只是不工作。显然,我一定错过了一些非常明显的东西。
我提交了 .gitignore,但是 .DS_Store 仍然出现在状态中。然后我删除了 .DS_Store 使用 git rm --cached .DS_Store (以防万一,即使它不在我的仓库中)。
没有。现在我看到它在暂存区中显示为“要提交的更改 => 已删除:.DS_Store”。
有没有办法完全摆脱它?所以它不再在我的状态中弹出了?
这里是:
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: .DS_Store
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
modified: assets/.DS_Store
modified: assets/stylesheets/main.css
modified: index.html
这里的(相当轻微的)问题是您有一定数量的 existing 提交,其中 .DS_Store
存在。请注意,当前状态指示至少有两个这样的文件,一个在树的顶层,一个在 assets
:
deleted: .DS_Store
modified: assets/.DS_Store
无法更改这些现有提交。他们将永远保留 .DS_Store
文件的副本(或者只要这些提交继续存在,无论如何)。
您必须从Git的索引中删除这些.DS_Store
文件(全部)如果您希望它们 而不是 存储在以后的提交中。通过这样做——运行ning git rm --cached
并进行提交——你告诉 Git 当你检查这些历史提交之一时,它应该提取历史 .DS_Store
文件,并且当您从该历史提交切换到 缺少 这些 .DS_Store
文件的更现代的提交之一时,Git 应该 删除 他们。
由于 macOS Finder 会在文件丢失时创建一个新的 .DS_Store
每当它在 Finder window 中显示目录时,此特定操作在 中足够安全这个特殊情况。但是,如果您还需要对它们使用 git rm --cached
,那么对于 other 文件,有几件事情需要注意,这可能会使这变得更加棘手。
可选阅读:为什么这么复杂
Git的index,有这个比较烂的名字(index?是什么index-ing?),还有另外两个名字。 Git也称这个东西为staging area,指的是你如何使用它,cache,指的是它的使用方式内部使用。名称“缓存”主要出现在 git rm --cached
的拼写中,它告诉 Git 将其从索引中删除,而不是将其从工作树中删除。
好的,我们给这东西取了三个名字。这告诉我们什么?嗯,一方面,它告诉我们 Git 的索引 非常重要 。事实上,这绝对是至关重要的。但为什么?为什么 Git 坚持要一遍又一遍地把它的索引推到我们脸上?最终,那个 问题的真正答案只是“这是一个深思熟虑的选择”——但值得研究让 Linus Torvalds 做出这个选择的因素。结果是从 commits.
开始
Git 最后,都是关于提交的。这与 files 无关,尽管从某种意义上说,文件包含在每个提交中。这也与 b运行ch names 无关,尽管 b运行ch names 对帮助你是必要的(和 Git)找到 提交。但是,提交 是 存储库中的历史记录。它们保存文件,并形成我们有时称为 b运行ches 的东西(参见 What exactly do we mean by "branch"?)。
每个提交都由一个丑陋的大哈希 ID 编号进行编号。每个提交存储两件事:
- 在您(或任何人)做出 提交时,Git 知道的所有文件的快照;和
- 元数据,或有关提交本身的信息,例如提交人、时间和原因(您的日志消息)。
在提交的元数据中,每个提交都包含一些较早提交的哈希ID,这就是使提交充当历史记录的原因。我们不会在这里深入细节,但这就是 b运行ches 实际工作的方式。
这里要知道的关键一点是任何提交的任何部分都不能更改。这是因为 of 提交的哈希 ID 是 in 提交中所有数据的校验和。 Git 在进行提交时计算这些校验和,并在提取提交时验证它们。如果它们不匹配,则提交在存储中已损坏,1 并且无法使用。
因此,所有存储在中 提交的文件都是read-only。它们也被压缩(以节省 space)和 de-duplicated(以节省 space 和时间)。如果连续两次提交共享 1000 个文件中的 999 个,他们 字面上 共享文件:只有一个 changed 文件必须进入存储后来的承诺。但这意味着 committed 文件对于完成任何新工作完全无用:
- 您无法更改它们,并且
- 大多数程序甚至无法读取它们。
所以Git必须将提交提取到可用区域。 Git 将此区域称为您的 工作树 或 work-tree,因为这是您工作的地方。这里的文件是普通的日常文件,你可以完成工作。
那么 Git 需要什么——这在所有版本控制系统中都很常见;他们都共享这种设置——是:
- 已提交,未更改历史 个文件;一个
- 一个工作区(工作space或工作树或任何你喜欢的),你可以在那里完成工作。
在Git的情况下,工作区实际上是您的,您可以随意使用。这意味着您可以在其中创建您 不 想要 Git 到 save-for-all-time 的文件。您可能会认为,这就是 .gitignore
的用武之地。这个假设并不是 错误的 ,而是 不完整的 。
1存储媒体做失败,在现实世界中。大多数故障都会被检测到,但也有可能——通常声称约为 1016 中的 1 或更好——可能会遗漏某些故障,从而返回错误数据。 Google 做了分析,发现实际错误率往往比声称的要高。
索引
Git 真正需要的是要提交的文件列表。也就是说,假设您正在 work-tree 中工作。您创建了一堆文件——可能是数百个、数千个或其他。 其中两个 文件应作为新文件进入下一个 提交,其余文件应被忽略。
一种可能的处理方法是只拥有一个“忽略这些文件”文件,并从“忽略这些文件”文件中未列出的每个文件自动生成 files-to-be-committed 列表。但是如果你尝试一下,你会发现它是 error-prone。 Git 和几个类似的版本控制系统使用明确的“添加一些文件”命令来 添加 它们到文件列表。
索引,那么,可能只是一种清单:这些是要包含的文件;当您询问状态 时,所有其他文件都将被称为未跟踪。假设是这种情况,并且您说 添加所有文件 。您没有明确告诉 Git 忽略 .DS_Store
文件。他们进入列表。您进行了提交,并且提交具有 .DS_Store
个文件。后来,您意识到您没有打算提交.DS_Store
个文件。
太晚了。这些提交现在存在。无论你对清单做什么,最多,你只是要从 future 提交中省略 .DS_Store
文件。您无法修复现有的提交,因为它们是 read-only。充其量,您可以返回所有旧提交,将它们一一取出,删除 .DS_Store
文件,然后进行 新的和改进的 提交,否则是一样的与原始文件一样,但现在缺少 .DS_Store
个文件。
(事实上你可以做到这一切。但这意味着你需要让其他人——所有其他拥有你的存储库克隆的人——停止使用旧的承诺支持新的和改进的承诺。)
现在,Git 的索引与 Mercurial 的清单相比特别不寻常的原因是有了这个文件列表,Linus 决定 expose,并用它做一些特殊的技巧:
该索引不仅包含进入下一次提交的所有文件的名称——最初,通过提取您提交的任何文件来填充git checkout
——而且还包含内部 Git 每个此类文件的 blob 哈希 ID。
在合并期间,索引 扩展 一次最多容纳三个文件,所有文件都具有相同的 name.
git commit
命令懒得看你的work-tree.2 相反,它只是在 运行 git commit
时打包 在 索引中的任何内容。这非常快,因为那些内部 blob 哈希 ID 是 Git 存储文件的方式:事实上,它们已经存在,pre-compressed 和 pre-de-duplicated.
git add
命令相当于:压缩和de-duplicate这些文件并将它们放入您的索引中,替换任何以前的同名文件,或者如果没有以前的文件.3
则创建一个新条目
git rm
命令意味着从你的索引和我的work-tree中删除文件。添加 --cached
意味着 保留我的 work-tree 副本。
所有这一切的一个结果是 git commit
不会提交您的 work-tree 中的内容。您可以使用此 属性 来处理 work-tree 中的文件以进行测试,而无需实际提交测试代码。这可能是好事也可能是坏事;不同的人对它是好还是坏有不同的看法;但这就是 Linus 选择这样做的方式,这种行为现在已经深深植根于许多 Git 用户的心中。
这一切归结为一个相对简单的陈述:索引始终保持您的提议的下一次提交,否则保持合并冲突还没有解决所以当前不可能进行提交。 如果我们忽略合并冲突的情况,您可以将索引视为持有您提议的下一次提交。
当检查一些现有的提交时,Git 从该提交的 填充它的索引 ,然后使用填充的索引用文件填充您的 work-tree .这意味着 Git 现在已准备好进行 new 提交,这将与当前提交完全匹配。4
2为了可用性,这很久以前做了一点改变:git commit
现在 运行s git status
内部,并产生一个 commented-out git status
提交消息中您可以编辑的部分。
3事实上,git add
也可以表示使索引匹配,如果你删除一个work-tree文件,git add
可以删除那个文件的索引副本。例如:rm path/to/file; git add path/to/file
是 运行 宁 git rm path/to/file
.
的 long-winded 方式
4如果索引和当前提交 do 匹配,git commit
通常会拒绝进行新的提交,迫使您使用 git commit --allow-empty
进行提交。新提交不是 empty——它包含索引中的任何内容——但与当前提交的 difference 将为空。
到目前为止的总结
Git 不会从您的工作树中进行新的提交,因此您的 .gitignore
文件的内容与 git commit
命令无关。相反,Git 从 Git 的索引中的任何内容进行新提交。 Git 的索引索引的内容通常来自 current commit.5
一旦你添加了一些文件,然后,文件 继续进入新的提交 直到你明确地 删除 它。无论文件名是否在 .gitignore
文件中,都是如此。要使该文件真正消失,您必须 将其删除。那么当前提交和下一次提交之间的区别将包括 删除 文件。
那么:做什么 列出文件名、目录名、模式,或者任何你可以在 .gitignore
文件中列出的东西,在 .gitignore
做?有什么好处?
5这条规则有一些例外;参见,例如 Checkout another branch when there are uncommitted changes on the current branch.
.gitignore
的作用
.gitignore
(或任何其他排除文件,如 .git/info/exclude
)有两种有用的东西,还有一种危险的东西:
首先是en-massegit add
操作,比如git add --all
或者git add .
或者git add *
.6 或者,就此而言,您可以在 .gitignore
中列出类似 *.pyc
的文件模式,然后 运行 git add file.pyc
无论如何。这里发生的事情很简单:如果文件不在 Git 的索引中,并且名称在排除文件中,git add
不会添加它。
这意味着如果一个文件当前未被跟踪——请参阅下面的未跟踪定义——它保持未跟踪状态。但如果文件已经在 Git 的索引中,则 .gitignore
条目 无效 .
其次,当您 运行 git status
时,Git 会经常抱怨各种文件未被跟踪。在排除文件中列出名称或模式 停止抱怨。
我们马上就会谈到危险的事情。现在让我们定义 tracked。 Git 中的跟踪文件是当前在 Git 的索引中的文件。 就是这样。真的就这么简单。如果您 work-tree 中的某个文件现在 Git 的索引 中,则它会被跟踪。如果它现在 Git 的索引 中不存在,则它未被跟踪。
记住 Git 的索引内容会改变!如果你 git checkout
一些提交,Git 填充它的索引。现在跟踪这些文件。如果您 运行 git add
在一个新文件上,该文件将进入 Git 的索引。现在跟踪该文件。如果您 运行 git rm
—有或没有 --cached
—在一个文件上,该文件来自 out Git 的索引。该文件现在 未跟踪 。当然,如果你 运行 git rm
没有 --cached
,那个文件也会从你的 work-tree 中消失。7
git status
的作用是 运行 two git diff
命令:
- 第一个
git diff
将 当前提交 与 Git 的索引进行比较。对于相同的每个文件,Git 什么都不说。对于每个不同、新的或删除的文件,Git 表示该文件暂存以提交,并进行修改,添加或删除。
- 第二个
git diff
将 Git 的索引中的内容与您的 work-tree 中的内容进行比较。对于相同的每个文件,Git 什么都不说。对于 不同 的文件,Git 表示该文件 未暂存提交 。什么是这里不寻常的是,对于 new 的文件,Git 调用这些文件 untracked。
当然,最后一点是因为未跟踪文件的定义。
在 .gitignore
中列出文件会使 git status
闭嘴 关于 untracked-ness。它对实际的 tracked-ness 根本没有任何影响!它只是让抱怨闭嘴。
在 .gitignore
(或其他一些排除文件)中列出文件名或模式的最后一件事是事情有点危险。这将授予 Git 权限 销毁 这样的文件:
- 假设您正在提交
a123456...
,其中 没有 有一个 .DS_Store
文件,并且有一个 .DS_Store
文件中的 work-tree。也就是说,.DS_Store
目前 未被追踪。
- 您现在发出
git checkout
命令来检出提交 4321cab...
,其中 确实 有一个 .DS_Store
文件。
要提取提交 4321cab...
,Git 必须将 .DS_Store
文件放入 Git 的索引中,然后将该文件复制到您的 work-tree。您的 work-tree 中已经有一个 .DS_Store
文件。此文件将被覆盖。
通常,Git会停下来抱怨:嘿,如果我提取提交4321cab...
,我会破坏你的.DS_Store
文件! 如果它是宝贵的数据,这使您有机会将其移开。但是,如果您将文件列为 可忽略,Git 将随意破坏它。
由于 .DS_Store
中的数据很少被认为是珍贵的,所以在这里可能没问题。但总的来说要小心。
6Git 命令中 *
的精确操作取决于您是否使用 Unix-style shell 例如 bash
,或 DOS-style command-interpreter 例如 CMD.EXE
,但是 Git 本身会进行 glob 扩展,所以结果非常相似。不过,我们不会在此处介绍细微的差异。
7有点哲学倾向的练习:如果名为 ghost
的文件不 在您的 work-tree 并且不在 Git 的索引中,non-existent ghost
文件是否也未被跟踪? (它不在 Git 的索引中,所以无论如何它都不会在下一次提交中。)那么 是 的名为 ghost
的文件呢?在 Git 的索引中,但不在您的 work-tree 中?这个文件被跟踪了吗?它会在下一次提交中吗?
我搜索了..我阅读了我可以在这里找到的关于相似甚至相同问题的所有答案。我看了教程。当它发生在某人的终端上时,它看起来超级简单和合乎逻辑。在我的,它只是不工作。显然,我一定错过了一些非常明显的东西。 我提交了 .gitignore,但是 .DS_Store 仍然出现在状态中。然后我删除了 .DS_Store 使用 git rm --cached .DS_Store (以防万一,即使它不在我的仓库中)。 没有。现在我看到它在暂存区中显示为“要提交的更改 => 已删除:.DS_Store”。 有没有办法完全摆脱它?所以它不再在我的状态中弹出了?
这里是:
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: .DS_Store
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
modified: assets/.DS_Store
modified: assets/stylesheets/main.css
modified: index.html
这里的(相当轻微的)问题是您有一定数量的 existing 提交,其中 .DS_Store
存在。请注意,当前状态指示至少有两个这样的文件,一个在树的顶层,一个在 assets
:
deleted: .DS_Store modified: assets/.DS_Store
无法更改这些现有提交。他们将永远保留 .DS_Store
文件的副本(或者只要这些提交继续存在,无论如何)。
您必须从Git的索引中删除这些.DS_Store
文件(全部)如果您希望它们 而不是 存储在以后的提交中。通过这样做——运行ning git rm --cached
并进行提交——你告诉 Git 当你检查这些历史提交之一时,它应该提取历史 .DS_Store
文件,并且当您从该历史提交切换到 缺少 这些 .DS_Store
文件的更现代的提交之一时,Git 应该 删除 他们。
由于 macOS Finder 会在文件丢失时创建一个新的 .DS_Store
每当它在 Finder window 中显示目录时,此特定操作在 中足够安全这个特殊情况。但是,如果您还需要对它们使用 git rm --cached
,那么对于 other 文件,有几件事情需要注意,这可能会使这变得更加棘手。
可选阅读:为什么这么复杂
Git的index,有这个比较烂的名字(index?是什么index-ing?),还有另外两个名字。 Git也称这个东西为staging area,指的是你如何使用它,cache,指的是它的使用方式内部使用。名称“缓存”主要出现在 git rm --cached
的拼写中,它告诉 Git 将其从索引中删除,而不是将其从工作树中删除。
好的,我们给这东西取了三个名字。这告诉我们什么?嗯,一方面,它告诉我们 Git 的索引 非常重要 。事实上,这绝对是至关重要的。但为什么?为什么 Git 坚持要一遍又一遍地把它的索引推到我们脸上?最终,那个 问题的真正答案只是“这是一个深思熟虑的选择”——但值得研究让 Linus Torvalds 做出这个选择的因素。结果是从 commits.
开始Git 最后,都是关于提交的。这与 files 无关,尽管从某种意义上说,文件包含在每个提交中。这也与 b运行ch names 无关,尽管 b运行ch names 对帮助你是必要的(和 Git)找到 提交。但是,提交 是 存储库中的历史记录。它们保存文件,并形成我们有时称为 b运行ches 的东西(参见 What exactly do we mean by "branch"?)。
每个提交都由一个丑陋的大哈希 ID 编号进行编号。每个提交存储两件事:
- 在您(或任何人)做出 提交时,Git 知道的所有文件的快照;和
- 元数据,或有关提交本身的信息,例如提交人、时间和原因(您的日志消息)。
在提交的元数据中,每个提交都包含一些较早提交的哈希ID,这就是使提交充当历史记录的原因。我们不会在这里深入细节,但这就是 b运行ches 实际工作的方式。
这里要知道的关键一点是任何提交的任何部分都不能更改。这是因为 of 提交的哈希 ID 是 in 提交中所有数据的校验和。 Git 在进行提交时计算这些校验和,并在提取提交时验证它们。如果它们不匹配,则提交在存储中已损坏,1 并且无法使用。
因此,所有存储在中 提交的文件都是read-only。它们也被压缩(以节省 space)和 de-duplicated(以节省 space 和时间)。如果连续两次提交共享 1000 个文件中的 999 个,他们 字面上 共享文件:只有一个 changed 文件必须进入存储后来的承诺。但这意味着 committed 文件对于完成任何新工作完全无用:
- 您无法更改它们,并且
- 大多数程序甚至无法读取它们。
所以Git必须将提交提取到可用区域。 Git 将此区域称为您的 工作树 或 work-tree,因为这是您工作的地方。这里的文件是普通的日常文件,你可以完成工作。
那么 Git 需要什么——这在所有版本控制系统中都很常见;他们都共享这种设置——是:
- 已提交,未更改历史 个文件;一个
- 一个工作区(工作space或工作树或任何你喜欢的),你可以在那里完成工作。
在Git的情况下,工作区实际上是您的,您可以随意使用。这意味着您可以在其中创建您 不 想要 Git 到 save-for-all-time 的文件。您可能会认为,这就是 .gitignore
的用武之地。这个假设并不是 错误的 ,而是 不完整的 。
1存储媒体做失败,在现实世界中。大多数故障都会被检测到,但也有可能——通常声称约为 1016 中的 1 或更好——可能会遗漏某些故障,从而返回错误数据。 Google 做了分析,发现实际错误率往往比声称的要高。
索引
Git 真正需要的是要提交的文件列表。也就是说,假设您正在 work-tree 中工作。您创建了一堆文件——可能是数百个、数千个或其他。 其中两个 文件应作为新文件进入下一个 提交,其余文件应被忽略。
一种可能的处理方法是只拥有一个“忽略这些文件”文件,并从“忽略这些文件”文件中未列出的每个文件自动生成 files-to-be-committed 列表。但是如果你尝试一下,你会发现它是 error-prone。 Git 和几个类似的版本控制系统使用明确的“添加一些文件”命令来 添加 它们到文件列表。
索引,那么,可能只是一种清单:这些是要包含的文件;当您询问状态 时,所有其他文件都将被称为未跟踪。假设是这种情况,并且您说 添加所有文件 。您没有明确告诉 Git 忽略 .DS_Store
文件。他们进入列表。您进行了提交,并且提交具有 .DS_Store
个文件。后来,您意识到您没有打算提交.DS_Store
个文件。
太晚了。这些提交现在存在。无论你对清单做什么,最多,你只是要从 future 提交中省略 .DS_Store
文件。您无法修复现有的提交,因为它们是 read-only。充其量,您可以返回所有旧提交,将它们一一取出,删除 .DS_Store
文件,然后进行 新的和改进的 提交,否则是一样的与原始文件一样,但现在缺少 .DS_Store
个文件。
(事实上你可以做到这一切。但这意味着你需要让其他人——所有其他拥有你的存储库克隆的人——停止使用旧的承诺支持新的和改进的承诺。)
现在,Git 的索引与 Mercurial 的清单相比特别不寻常的原因是有了这个文件列表,Linus 决定 expose,并用它做一些特殊的技巧:
该索引不仅包含进入下一次提交的所有文件的名称——最初,通过提取您提交的任何文件来填充
git checkout
——而且还包含内部 Git 每个此类文件的 blob 哈希 ID。在合并期间,索引 扩展 一次最多容纳三个文件,所有文件都具有相同的 name.
git commit
命令懒得看你的work-tree.2 相反,它只是在 运行git commit
时打包 在 索引中的任何内容。这非常快,因为那些内部 blob 哈希 ID 是 Git 存储文件的方式:事实上,它们已经存在,pre-compressed 和 pre-de-duplicated.
则创建一个新条目git add
命令相当于:压缩和de-duplicate这些文件并将它们放入您的索引中,替换任何以前的同名文件,或者如果没有以前的文件.3git rm
命令意味着从你的索引和我的work-tree中删除文件。添加--cached
意味着 保留我的 work-tree 副本。
所有这一切的一个结果是 git commit
不会提交您的 work-tree 中的内容。您可以使用此 属性 来处理 work-tree 中的文件以进行测试,而无需实际提交测试代码。这可能是好事也可能是坏事;不同的人对它是好还是坏有不同的看法;但这就是 Linus 选择这样做的方式,这种行为现在已经深深植根于许多 Git 用户的心中。
这一切归结为一个相对简单的陈述:索引始终保持您的提议的下一次提交,否则保持合并冲突还没有解决所以当前不可能进行提交。 如果我们忽略合并冲突的情况,您可以将索引视为持有您提议的下一次提交。
当检查一些现有的提交时,Git 从该提交的 填充它的索引 ,然后使用填充的索引用文件填充您的 work-tree .这意味着 Git 现在已准备好进行 new 提交,这将与当前提交完全匹配。4
2为了可用性,这很久以前做了一点改变:git commit
现在 运行s git status
内部,并产生一个 commented-out git status
提交消息中您可以编辑的部分。
3事实上,git add
也可以表示使索引匹配,如果你删除一个work-tree文件,git add
可以删除那个文件的索引副本。例如:rm path/to/file; git add path/to/file
是 运行 宁 git rm path/to/file
.
4如果索引和当前提交 do 匹配,git commit
通常会拒绝进行新的提交,迫使您使用 git commit --allow-empty
进行提交。新提交不是 empty——它包含索引中的任何内容——但与当前提交的 difference 将为空。
到目前为止的总结
Git 不会从您的工作树中进行新的提交,因此您的 .gitignore
文件的内容与 git commit
命令无关。相反,Git 从 Git 的索引中的任何内容进行新提交。 Git 的索引索引的内容通常来自 current commit.5
一旦你添加了一些文件,然后,文件 继续进入新的提交 直到你明确地 删除 它。无论文件名是否在 .gitignore
文件中,都是如此。要使该文件真正消失,您必须 将其删除。那么当前提交和下一次提交之间的区别将包括 删除 文件。
那么:做什么 列出文件名、目录名、模式,或者任何你可以在 .gitignore
文件中列出的东西,在 .gitignore
做?有什么好处?
5这条规则有一些例外;参见,例如 Checkout another branch when there are uncommitted changes on the current branch.
.gitignore
的作用
.gitignore
(或任何其他排除文件,如 .git/info/exclude
)有两种有用的东西,还有一种危险的东西:
首先是en-masse
git add
操作,比如git add --all
或者git add .
或者git add *
.6 或者,就此而言,您可以在.gitignore
中列出类似*.pyc
的文件模式,然后 运行git add file.pyc
无论如何。这里发生的事情很简单:如果文件不在 Git 的索引中,并且名称在排除文件中,git add
不会添加它。这意味着如果一个文件当前未被跟踪——请参阅下面的未跟踪定义——它保持未跟踪状态。但如果文件已经在 Git 的索引中,则
.gitignore
条目 无效 .其次,当您 运行
git status
时,Git 会经常抱怨各种文件未被跟踪。在排除文件中列出名称或模式 停止抱怨。
我们马上就会谈到危险的事情。现在让我们定义 tracked。 Git 中的跟踪文件是当前在 Git 的索引中的文件。 就是这样。真的就这么简单。如果您 work-tree 中的某个文件现在 Git 的索引 中,则它会被跟踪。如果它现在 Git 的索引 中不存在,则它未被跟踪。
记住 Git 的索引内容会改变!如果你 git checkout
一些提交,Git 填充它的索引。现在跟踪这些文件。如果您 运行 git add
在一个新文件上,该文件将进入 Git 的索引。现在跟踪该文件。如果您 运行 git rm
—有或没有 --cached
—在一个文件上,该文件来自 out Git 的索引。该文件现在 未跟踪 。当然,如果你 运行 git rm
没有 --cached
,那个文件也会从你的 work-tree 中消失。7
git status
的作用是 运行 two git diff
命令:
- 第一个
git diff
将 当前提交 与 Git 的索引进行比较。对于相同的每个文件,Git 什么都不说。对于每个不同、新的或删除的文件,Git 表示该文件暂存以提交,并进行修改,添加或删除。 - 第二个
git diff
将 Git 的索引中的内容与您的 work-tree 中的内容进行比较。对于相同的每个文件,Git 什么都不说。对于 不同 的文件,Git 表示该文件 未暂存提交 。什么是这里不寻常的是,对于 new 的文件,Git 调用这些文件 untracked。 当然,最后一点是因为未跟踪文件的定义。
在 .gitignore
中列出文件会使 git status
闭嘴 关于 untracked-ness。它对实际的 tracked-ness 根本没有任何影响!它只是让抱怨闭嘴。
在 .gitignore
(或其他一些排除文件)中列出文件名或模式的最后一件事是事情有点危险。这将授予 Git 权限 销毁 这样的文件:
- 假设您正在提交
a123456...
,其中 没有 有一个.DS_Store
文件,并且有一个.DS_Store
文件中的 work-tree。也就是说,.DS_Store
目前 未被追踪。 - 您现在发出
git checkout
命令来检出提交4321cab...
,其中 确实 有一个.DS_Store
文件。
要提取提交 4321cab...
,Git 必须将 .DS_Store
文件放入 Git 的索引中,然后将该文件复制到您的 work-tree。您的 work-tree 中已经有一个 .DS_Store
文件。此文件将被覆盖。
通常,Git会停下来抱怨:嘿,如果我提取提交4321cab...
,我会破坏你的.DS_Store
文件! 如果它是宝贵的数据,这使您有机会将其移开。但是,如果您将文件列为 可忽略,Git 将随意破坏它。
由于 .DS_Store
中的数据很少被认为是珍贵的,所以在这里可能没问题。但总的来说要小心。
6Git 命令中 *
的精确操作取决于您是否使用 Unix-style shell 例如 bash
,或 DOS-style command-interpreter 例如 CMD.EXE
,但是 Git 本身会进行 glob 扩展,所以结果非常相似。不过,我们不会在此处介绍细微的差异。
7有点哲学倾向的练习:如果名为 ghost
的文件不 在您的 work-tree 并且不在 Git 的索引中,non-existent ghost
文件是否也未被跟踪? (它不在 Git 的索引中,所以无论如何它都不会在下一次提交中。)那么 是 的名为 ghost
的文件呢?在 Git 的索引中,但不在您的 work-tree 中?这个文件被跟踪了吗?它会在下一次提交中吗?