在不提交的情况下本地删除并忽略文件夹

Locally delete and ignore folder without commiting

我们的存储库中有一个其他人依赖的文件夹,但我想删除我的本地工作副本。我想确保我不会不小心提交此更改。如果我只是删除该文件夹,我的 git 索引就会被该文件夹中的大量删除内容填满。有没有办法让 git 忽略该文件夹的删除?

我尝试将文件夹路径添加到 .git/info/exclude 但这似乎是为了防止本地文件被提交。

简短的回答是否定的。有一个更长的答案是 yes but——具体来说,是的,但是要小心!具体来说,您可以在索引中设置 skip-worktree 位。 Git的sparse checkout模式使用了这个位,你可以自己使用,达到同样的效果:

git update-index --skip-worktree <list of files>

不过在这种情况下,您可能只想首先设置稀疏结帐。

索引正在索引(因此名称为 index)您的工作树:它列出了 应该 存在的所有文件,并且它们的内容实际上将在您所做的 next 提交中,当然除非您在进行下一次提交之前修改索引。我稍后会了解 应该存在的 的真正含义,但让我们先看看正常情况。

如果您从工作树中删除所有文件(及其包含的目录/文件夹),Git 会注意到您的索引和工作树不匹配,并告诉您您有这些差异,即所有这些文件都被删除。它们未暂存提交,因为文件仍在索引中,每个文件的副本 索引匹配当前提交中每个文件的副本。但是它们 从工作树中消失了:它们 被删除了。

如果您也从索引中删除文件(使用 git rm --cached),您的索引和工作树现在将匹配:索引不会列出 dir/file,并且 dir/file 实际上并不存在。所以这部分git status的输出就不会再抱怨dir/file了。但是如果你这样做,现在你的 current 提交,Git 调用 HEAD@doesdir/file,而你的索引 没有 dir/file,所以你的 下一次提交 也会没有dir/file。这意味着删除 dir/file 暂存提交 并且 git status 将报告 that.

换句话说,如果工作树中缺少 dir/file,但在 @(当前或 HEAD 提交)中,您只有两个选择:

  • dir/file 在索引中是。然后根据索引与工作树删除它。 git status会这么说。

  • dir/file 在索引中 不是 。然后根据@-vs-index删除。 git status会这么说。

如果您不打算进行缺少 dir/file 的提交,前者显然是更好的选择 — 但它仍然很嘈杂。

应该存在是什么意思

1请注意,如果索引说路径为 P 的文件应该存在,并且确实存在,那么一切都很好。工作树中P中的文件数据与索引中P中的数据匹配,或者不匹配,文件数据P 中的索引匹配或不匹配 @HEAD 提交中的内容。

另一方面,如果索引表明路径为 P 的文件 not 存在于工作树中,但是事实上,文件 确实 存在于工作树中,然后路径 P 表示一个 未跟踪的文件 。这是 .gitignore 和其他排除文件的用武之地:您可以告诉 git status 不要通过将 P 列在 .gitignore 中来抱怨它。

第三种情况当然是您正在查看的情况:路径为 P 的文件确实存在于索引中,但在工作树中缺失。

稀疏签出和跳过工作树位

Git 内置了对 Git 所谓的 稀疏结帐 的直接支持。为此,您将配置变量 core.sparseCheckout 设置为 true,并在 .git/info/sparse-checkout 中列出路径(或路径规范)。有关详细信息,请参阅 Is it possible to do a sparse checkout without checking out the whole repository first? The git read-tree documentation section on sparse checkouts 也有更多相关信息。

稀疏检出工作的方式是Git像往常一样将整个提交读入索引,而不是将所有相应的文件复制到工作树中,它只会将 selected 文件复制到工作树中。对于剩余的文件,可能在也可能不在工作树中——因为 Git 不会查找——它在索引条目中设置 skip-worktree 位 那个文件。

git status 或其他 Git 操作扫描实际工作树以查看 真正 那里的内容时,如果他们遇到索引条目设置了 skip-worktree 位后,他们假装文件在那里,其内容列在索引中。他们竭力避免检查文件是否真的存在。根据 skip-worktree 位,索引声明的内容必须假定为真。

如果您使用稀疏校验,Git 将自行维护 skip-worktree 位(至少在某种程度上——我没有试验过该功能以查看它可能有粗糙边缘的地方)。否则你必须自己维护它们,手动设置(git update-index --skip-worktree)和清除(git update-index --no-skip-worktree)每个文件的位。