"git status"命令中未跟踪的文件未显示出来。

36

我的项目具有以下文件夹结构:

所有项目文件都在名为base_fldr的文件夹中。此外,我在base_fldr内还有几个名为sub_fldr1sub_fldr2的子文件夹。这些子文件夹也包含一些文件。

如果我修改了base_fldr或者base_fldr\sub_fldr\中的任何文件,则git status会将它们显示为已修改。同时,如果我在base_fldr中添加新文件,则git status会将其显示为未跟踪文件。

我的问题是,如果我在base_fldr\sub_fldr\中添加新文件,则git status不会将该文件显示为未跟踪文件。它甚至不会提供有关该文件的任何信息。

该文件及其扩展名都不在我的.gitignore列表中。而且,我尝试过使用git add sub_fldr\file_name命令,但它既没有报错,也没有将该文件添加到索引中。

有什么想法吗?谢谢!


3
如果你运行 git status -u,这个文件会显示出来吗? - Peter Coulton
1
没有。git status -u显示了我base_fldr中新添加的文件,但没有显示base_fldr \ sub_fldr中的文件。 - kriver
8个回答

28

我找出了问题所在。基本上,我的.gitignore文件中的第一行是“*/”。这会导致git status命令忽略添加到子目录中的任何文件。但有趣的是,如果我修改子文件夹中的任何文件,则git status会正确显示它们已更改,因为该文件已经在git存储库中,但是会忽略子文件夹中的新文件。

我通过删除.gitignore文件中的那行来解决我的问题,以便不再忽略子文件夹中的更改,然后将新文件添加到索引中,再将.gitignore文件中的那行重新添加回去,以便忽略子文件夹中的任何生成文件。

感谢各位的回复。


5
我也遇到了同样的问题,最终我意识到几个月前我已经毫无理由地将创建的文件夹名称添加到了.gitignore文件中!但是这个答案让我检查了一下,加一分给它;-1分给我,因为我在查看之前先搜索了StackOverflow。 - PandaWood
3
命令,为了完整起见:git status -u --ignored - Victor Sergienko

16

这可能是因为你的 base_fldr\sub_fldr\ 目录未被跟踪,如果你运行:

git add base_fldr\sub_fldr\

从你的工作副本根目录开始,它会自动添加该目录中的其他文件和目录,以及该目录中的文件和目录。

默认情况下,git 不会显示未跟踪目录中的文件。


OP说,在sub_fldr内修改的文件git status中显示出来。 - Greg Hewgill
我的 base_fldr\sub_fldr\ 被追踪了。实际上,如果我修改一个现有的文件,git 状态会正确地显示 sub_fldr 中的该文件已被修改。 - kriver

16

我遇到了一个类似的问题,即跟踪文件丢失。在尝试管理本地修改的已跟踪文件的方式时,我发现可以运行以下命令来避免不小心提交:

git update-index --assume-unchanged my-tracked-file-that-is-awol

我最终放弃了这个想法,但忘记撤销命令,所以对于这个文件和其他标记为 --assume-unchanged 的文件的后续更改完全丢失了:

git status -u --ignored

我花了一些时间才明白发生了什么,但我只需要用以下命令反转即可:

git update-index --no-assume-unchanged my-tracked-file-that-is-awol

这告诉我git在某种程度上忽略了一些被跟踪的文件,但我没有使用.gitignore。我发现我已经将要忽略的文件名(称其为“foo”)添加到.git/info/exclude中,但我的项目路径中有“foo”,例如src/foo/file-gone-awol。 - Udo Schuermann

8

你的 sub_fldr 文件夹里面有一个 .git 子目录吗?Git 可能会认为你正在尝试使用 子模块


子文件夹内没有 .git 目录。 - kriver
如果您在下面有一个.git子目录,更改仍应显示在父目录中。 - quantumpotato
确保你已经设置了“显示所有文件”选项 - 这让我忙了几个小时。我有一个“.git”子目录,但我看不到它。但是Git可以... - TobyEvans

7
为了调试此类问题,请观察以下两个输出,看看您的.gitignore文件是否是罪魁祸首:
1. git ls-files --other --directory --exclude-standard。这将显示所有未跟踪的文件,同时遵守.gitignore文件。
2. git ls-files --other --directory。这将显示所有未跟踪的文件,而不遵守.gitignore文件。
无论哪些文件出现在2的输出中,但在1的输出中不存在,都不会因为.gitignore文件中的某个标志而显示为未跟踪。请参考https://git-scm.com/docs/git-ls-files

2

这是导致此问题行为的另一个原因(git status未跟踪文件列表不包括子文件夹中未跟踪的文件)。如果该文件由于子文件夹中的.gitignore文件而未跟踪,则该文件将不会包含在git status未跟踪文件列表中。


0

你可能会在使用 chmod 修改的文件中遇到该错误。

使用 git status -u 命令,你可以在 "Untracked files" 中看到它们,但是使用 git diff 命令时,它们都没有显示任何差异。


0

从2011年开始,这是在Git v1.8.3-rc0(2013年4月)中首次修复的。
它修复了在代码遍历工作树以查找未跟踪和/或被忽略的文件时遇到的一些问题,并且在总体上清理和优化了代码路径。

查看提交0aaf62b, 提交defd7c7, 提交8aaf8d7, 提交b07bc8c, 提交95c6f27, 提交6cd5c58, 提交46aa2f9, 提交5bd8e2d, 提交be8a84c, 提交c94ab01, 提交184d2a8, 提交0104c9e, 提交289ff55, 提交560bb7a (2013年4月15日) 由Karsten Blees (kblees)提交。
(由Junio C Hamano -- gitster --合并于提交7093d2c, 2013年4月23日)

dir.c:使“git-status --ignored”在前导目录中工作

签名作者:Karsten Blees

如果“path”的某个组件被分类为未跟踪,则“{{link2:git status --ignored path/}}”不会列出“path”中被忽略的文件和目录。

在遍历前导目录时禁用DIR_SHOW_OTHER_DIRECTORIES标志。这可以防止带有DIR_SHOW_IGNORED标志的treat_leading_path()在顶级未跟踪目录处中止。

作为副作用,这也消除了每个前导目录级别的递归目录扫描,因为当从treat_leading_path()调用treat_directory()时,treat_directory()不能再调用read_directory_recursive()


但是,6年后(2019年末),随着Git 2.25(2020年第一季度)的推出,对目录遍历API进行了各种修复...撤销了上述的修复,并重新实现了它。

请查看 2019年12月20日由Junio C Hamano (gitster)提交的提交6836d2f
请查看 2019年12月19日提交的提交c847dfa, 2019年12月19日提交的提交777b420, 2019年12月19日提交的提交b9670c1,以及 2019年12月10日由Elijah Newren (newren)提交的提交c5c4edd, 2019年12月10日提交的提交072a231, 2019年12月10日提交的提交2f5d384, 2019年12月10日提交的提交a2b1336, 2019年12月10日提交的提交452efd1
(由Junio C Hamano -- gitster --2019年12月25日提交的提交d2189a7中合并)

Revert "dir.c: make 'git-status --ignored' work within leading directories"

Signed-off-by: Elijah Newren

Commit be8a84c52669 ("[dir.c](https://github.com/git/git/blob/a2b13367fe55bdeb10862f41aff3e2446b63e171/dir.c): make 'git-status --ignored' work within leading directories", 2013-04-15, Git v1.8.3-rc0 -- merge) noted that

git status --ignored <SOMEPATH>

would not list ignored files and directories within <SOMEPATH> if <SOMEPATH> was untracked, and modified the behavior to make it show them.

However, it did so via a hack that broke consistency; it would show paths under <SOMEPATH> differently than a simple

git status --ignored | grep <SOMEPATH>

would show them.

A correct fix is slightly more involved, and complicated slightly by this hack, so we revert this commit (but keep corrected versions of the testcases) and will later fix the original bug with a subsequent patch.

Some history may be helpful:

A very, very similar case to the commit we are reverting was raised in commit 48ffef966c76 ("ls-files: fix overeager pathspec optimization", 2010-01-08, Git v1.7.0-rc0 -- merge); but it actually went in somewhat the opposite direction.

In that commit, it mentioned how

git ls-files -o --exclude-standard t/

used to show untracked files under t/ even when t/ was ignored, and then changed the behavior to stop showing untracked files under an ignored directory.

More importantly, this commit considered keeping this behavior but noted that it would be inconsistent with the behavior when multiple pathspecs were specified and thus rejected it.

The reason for this whole inconsistency when one pathspec is specified versus zero or two is because common prefixes of pathspecs are sent through a different set of checks (in treat_leading_path()) than normal file/directory traversal (those go through read_directory_recursive() and treat_path()).

As such, for consistency, one needs to check that both codepaths produce the same result.

Revert commit be8a84c526691667fc04a8241d93a3de1de298ab, except instead of removing the testcase it added, modify it to check for correct and consistent behavior.

和:

dir: 修复对公共前缀目录的检查

签名:Elijah Newren

许多年前,目录遍历逻辑有一个优化,它总是会递归到所有路径规范的公共前缀目录,而不需要遍历前导目录以进入所需的目录。

因此,

git ls-files -o .git/                        # 情况 A

会注意到.git/是所有路径规范的公共前缀(因为它是唯一列出的路径规范),然后遍历它并开始显示该目录下的未知文件。

不幸的是,.git/不是我们应该遍历的目录,这使得这个优化变得有问题。

这也影响了像:

git ls-files -o --exclude-standard t/        # 情况 B

其中t/.gitignore文件中,因此不重要,不应递归进入。

它还影响了像:

git ls-files -o --directory untracked_dir/   # 情况 C

其中untracked_dir/确实未被跟踪,因此很有趣,但--directory标志意味着我们只想显示目录本身,而不是递归进入并开始列出其下的未跟踪文件。

情况B类错误在提交16e2cfa90993 ("read_directory(): further split treat_path()", 2010-01-08)和48ffef966c76 ("ls-files: fix overeager pathspec optimization", 2010-01-08, Git v1.7.0-rc0 -- merge)中得到了注意和修复,其思想是我们首先要检查公共前缀是否有趣。

前一个补丁指出,在检查公共前缀时不能使用treat_path(),因为treat_path()需要一个dir_entry(),而我们在检查公共前缀时还没有读取任何目录。

因此,该补丁从treat_path()中分离出treat_one_path()

后一个补丁创建了一个新的treat_leading_path(),手动复制了treat_path()的一些位,这些位无法分解,然后对其余部分调用treat_one_path()

这种方法有三个问题:

  • treat_leading_path()中的重复逻辑意外地错过了特殊路径的检查(例如is_dot_or_dotdot和匹配".git"),导致A类错误继续存在。
  • treat_leading_path()逻辑假定我们应该遍历任何路径处理不是path_none的内容,即它使C类错误持续存在。
  • 它意味着我们需要保持同步的分裂逻辑,这样就有可能出现新的不一致性(例如在commit be8a84c52669中,我们在本系列中撤消了它,或者在commit df5bcdf83ae中,我们将在随后的提交中修复

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接