繁体   English   中英

.gitignore、git-status 和 git-check-ignore 的意外行为

[英]Unexpected behavior with .gitignore, git-status and git-check-ignore

我将 Git 用于 Windows 版本 2.34.1 x86。 我有一个包含以下内容的文件夹(所有路径名都相对于该文件夹):

.git/
.gitignore
.vs/OS1/FileContentIndex/a
.vs/OS1/v17/Browse.VC.db
.vs/OS1/v17/Solution.VC.db
.vs/OS1/v17/ipch/AutoPCH/a
econv.txt

正如我们所见,文件夹本身在 Git 控制之下。 但是,上面显示的文件或文件夹都没有被暂存或提交,除了已经被跟踪的.gitignore

在以下两种情况下,我无法理解git statusgit check-ignore的不同行为:

情况一

.gitignore有以下内容:

/.vs/**/
!*/

git status输出(缩短为有趣的部分)

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .vs/OS1/FileContentIndex/
        .vs/OS1/v17/Browse.VC.db
        .vs/OS1/v17/Solution.VC.db
        .vs/OS1/v17/ipch/
        econv.txt

git check-ignore -v.vs/OS1/FileContentIndex/输出

.gitignore:3:!*/        .vs/OS1/FileContentIndex/

这意味着.vs/OS1/FileContentIndex/不会被忽略。 这与上述 output 的git status一致。 到目前为止,一切都很好。

情况2

.gitignore已进行了最低限度的更改,现在包含

/.vs/**
!*/

git status输出(缩短为有趣的部分)

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        econv.txt

git check-ignore -v.vs/OS1/FileContentIndex/输出

.gitignore:3:!*/        .vs/OS1/FileContentIndex/

问题

我了解情况 1 中的行为。 git check-ignore.vs/OS1/FileContentIndex/告诉我.vs/OS1/FileContentIndex/没有被忽略,因此git status将其放入未跟踪文件列表(尚未添加、暂存或提交)。

但我无法理解情况 2 中的行为。在这里, git check-ignore.vs/OS1/FileContentIndex/产生与情况 1 中相同的 output ,这再次意味着.vs/OS1/FileContentIndex/不会被忽略。

但是, git status不再包含在未跟踪文件列表中。 这对我来说似乎不一致,因为如果不忽略它,它应该出现在未跟踪文件列表中,不是吗?

有人可以解释那里发生了什么吗?

Git 从不存储任何目录(文件夹)。 但是.gitignore指令可以使 Git不查看文件夹内部,所以这里的事情变得混乱。

这条规则:

/.vs/**/

仅适用于文件夹,并告诉 Git“不要查看这些文件夹”。

这条规则:

!*/

也仅适用于文件夹,并告诉 Git:“每次都查看每个文件夹”。 由于第二条规则稍后出现,它会覆盖第一条规则。 由于第二条规则完全覆盖第一条规则,因此第一条规则无关紧要,可以在不改变任何行为的情况下删除。

当您将第一条规则更改为:

/.vs/**

它现在适用于文件夹和文件 这告诉 Git 对于.vs中的每个未跟踪文件,不应添加该文件。 由于根据定义,所有文件夹都未跟踪,因此它们也将被“忽略”(即,不查看内部)。 但是,下一个(未更改的)规则会覆盖文件夹的此状态,因此检查文件夹,即使它们位于.vs/下。 检查后,这些文件夹中的所有未跟踪文件都会通过第一条规则被忽略。 所以第一条规则现在很重要!

所以:

git status在未跟踪文件列表中不再有 [ .vs/OS1/FileContentIndex/ ]。

git status命令报告未跟踪的文件,而不是未跟踪的文件夹(根据定义,所有文件夹都是未跟踪的,因此这将是嘈杂且无用的)。 但是git status将通过剥离文件名部分并仅提及包含文件夹汇总一大堆文件,除非您使用git status选项之一来防止这种情况发生。

第一个git status列表:

 Untracked files: (use "git add <file>..." to include in what will be committed).vs/OS1/FileContentIndex/.vs/OS1/v17/Browse.VC.db.vs/OS1/v17/Solution.VC.db.vs/OS1/v17/ipch/ econv.txt

真正意思:

  • .vs/OS1/FileContentIndex/中的多个文件,未单独列出;
  • .vs/OS1/v17/Browse.VC.db ,单独列出
  • .vs/OS1/v17/Solution.VC.db ,单独列出
  • .vs/OS1/v17/ipch/中的多个文件,未单独列出
  • econv.txt ,单独列出

要使git status列出某些文件夹的特定文件,否则这些文件会像这样组合在一起,请使用-uall或更长的拼写--untracked-files=all

换一种方式...

换句话说:

  • 如果一个文件夹根本不包含任何文件,则它永远不会在git status output 中列出。 无法添加空文件夹。 另请参阅如何将空目录添加到 Git 存储库? (有一个适用于此的假或半假子模块的技巧)。
  • 如果文件夹包含一些文件,但所有这些文件当前都未被跟踪忽略,则它也不会列在git status output 中。 您的第二组.gitignore规则就是这种情况,即使仔细(递归地)一直向下查看所有子文件夹(根据定义浪费精力),它们也会小心地忽略.vs文件夹中的所有文件。
  • 如果文件夹包含一些跟踪文件但未修改,则这些文件不会列在git status output 中。 只有当它们被修改时,它们才会被列出。 1

1这里的“修改”包括在“为提交暂存的更改”output 部分中新增或删除的内容。 这是因为这是HEAD提交和当前索引内容之间的git diff --name-status 但是,根据定义,“未暂存以供提交”部分仅包括已删除或修改的文件,而不包括新文件。 这是因为第二部分的 output 来自 Git 索引中的内容和工作树中的内容之间的比较,如果文件不存在于 Git 的索引中,则根据定义它是untracked ,所以任何提及它 - 如果有的话任何此类——属于“未跟踪文件”部分。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM