未跟踪的文件未显示在 git status 中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4610561/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 09:45:34  来源:igfitidea点击:

untracked files not shown in git status

gitstatus

提问by kriver

I have a project with the following folder structure:

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

All the project files are in base_fldr folder. Also I have a few folders inside base_fldr called sub_fldr1 and sub_fldr2. These sub folders also contain some files.

所有项目文件都在 base_fldr 文件夹中。此外,我在 base_fldr 中有几个文件夹,名为 sub_fldr1 和 sub_fldr2。这些子文件夹还包含一些文件。

If I modify any of the files inside my base_fldr or base_fldr\sub_fldr\ then git status shows them as modified. Also if I add a new file to base_fldr, git status will show it as untracked file.

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

My problem is if I add a new file inside base_fldr\sub_fldr\ then the git status doesn't show the file as untracked. It won't even give any info about the file.

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

The file or its extension is NOT in my .gitignore list. Also I did try git add sub_fldr\file_name but neither it gave an error nor it add the file to index.

该文件或其扩展名不在我的 .gitignore 列表中。我也试过 git add sub_fldr\file_name 但它既没有给出错误也没有将文件添加到 index.html 。

Any idea what's happening here? Thanks!

知道这里发生了什么吗?谢谢!

采纳答案by kriver

I figured out what was going wrong. Basically the first line in my .gitignore file is "*/". This causes any file added to sub directory being ignored by git status command. But the funny thing was if I modify any files in sub folder, git status correctly shows them as modified as the file is already in git repository, but was ignoring new files in sub folder.

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

I fixed my issue by removing the line in .gitignore file to not ignore changes in sub folders, then added the new files to index and then again added back the line in .gitignore so that it will ignore any generated files in subfolders.

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

Thanks all for the responses.

感谢大家的回应。

回答by mveerman

I ran into a similar issue with missing tracked files. While experimenting with ways to manage locally modified versions of tracked files without having to constantly avoid accidental commits, I ran the following:

我遇到了丢失跟踪文件的类似问题。在尝试管理跟踪文件的本地修改版本而不必经常避免意外提交的方法时,我运行了以下命令:

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

I ended up scrapping this idea, but forgot to undo the command, so subsequent changes to this and other --assume-unchanged files were completely missing from:

我最终放弃了这个想法,但忘记撤消该命令,因此对这个文件和其他 --assume-unchanged 文件的后续更改完全缺失:

git status -u --ignored

It took me a while to figure out what was going on, but I simply had to reverse the command with:

我花了一段时间才弄清楚发生了什么,但我只需要使用以下命令来反转命令:

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

回答by Highway of Life

This is likely because your base_fldr\sub_fldr\ directory is untracked, if you run:

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

git add base_fldr\sub_fldr\

From within your working copy root, it will automatically add the directory and other files and directories within that directory as well.

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

By default, git will not show files within directories that are untracked.

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

回答by Greg Hewgill

Do you have a .gitsubdirectory inside your sub_fldrdirectory? Git may think you're trying to use submodules.

你的.git目录中有子目录sub_fldr吗?Git 可能认为您正在尝试使用submodules

回答by user13107

In order to debug an issue like this, see if your .gitignorefile is the culprit by observing the following two outputs

为了调试这样的问题,请.gitignore通过观察以下两个输出来查看您的文件是否是罪魁祸首

See https://git-scm.com/docs/git-ls-files

请参阅https://git-scm.com/docs/git-ls-files

  1. git ls-files --other --directory --exclude-standard
  1. git ls-files --other --directory --exclude-standard

This will show all untracked files, while obeying the .gitignorefile.

这将显示所有未跟踪的文件,同时遵守.gitignore文件。

  1. git ls-files --other --directory

  1. git ls-files --other --directory

This will show all untracked files, without obeying the .gitignorefile.

这将显示所有未跟踪的文件,而不遵守.gitignore文件。

Whichever files are present in output of 2, but are not present in output of 1, are not shown in untracked because of some flag in your .gitignorefile

输出中存在2但不存在于 输出1中的任何.gitignore文件都不会显示在未跟踪中,因为您的文件中存在某些标志

回答by user969350

Here is another cause of the behavior described in this question (git status untracked files list doesn't include an untracked file in a sub-folder). If the file is untracked because of a .gitignore file in the sub-folderthen the file won't be included in the git status untracked files list.

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

回答by VonC

Since 2011, this was fixed for the first time with Git v1.8.3-rc0 (April 2013).
It fixes a handful of issues in the code to traverse working tree to find untracked and/or ignored files, cleans up and optimizes the codepath in general.

自 2011 年以来,这在 Git v1.8.3-rc0(2013 年 4 月)中首次得到修复。
它修复了代码中的一些问题,以遍历工作树以查找未跟踪和/或忽略的文件,清理和优化代码路径。

See commit 0aaf62b, commit defd7c7, commit 8aaf8d7, commit b07bc8c, commit 95c6f27, commit 6cd5c58, commit 46aa2f9, commit 5bd8e2d, commit be8a84c, commit c94ab01, commit 184d2a8, commit 0104c9e, commit 289ff55, commit 560bb7a(15 Apr 2013) by Karsten Blees (kblees).
(Merged by Junio C Hamano -- gitster--in commit 7093d2c, 23 Apr 2013)

提交0aaf62b提交defd7c7提交8aaf8d7提交b07bc8c提交95c6f27提交6cd5c58提交46aa2f9提交5bd8e2d提交be8a84c提交c94ab01提交184d2a8提交0104c9e提交289ff55提交560bb7a由(2013年4月15日)卡斯滕Blees ( kblees)
(由Junio C gitsterHamano合并-- --提交 7093d2c 中,2013 年 4 月 23 日)

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

Signed-off-by: Karsten Blees

'git status --ignored path/' doesn't list ignored files and directories within 'path' if some component of 'path' is classified as untracked.

Disable the DIR_SHOW_OTHER_DIRECTORIESflag while traversing leading directories. This prevents treat_leading_path()with DIR_SHOW_IGNOREDflag from aborting at the top level untracked directory.

As a side effect, this also eliminates a recursive directory scan per leading directory level, as treat_directory()can no longer call read_directory_recursive()when called from treat_leading_path().

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

签字人: Karsten Blees

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

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

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



But, 6 years later (late 2019), with Git 2.25 (Q1 2020), an assorted fixes to the directory traversal API... revert that very fix seen above, and re-implement it.

但是,6 年后(2019 年末),在 Git 2.25(2020 年第一季度)中,对目录遍历 API 进行了各种修复……恢复上面看到的那个修复,并重新实现它。

See commit 6836d2f(20 Dec 2019) by Junio C Hamano (gitster).
See commit c847dfa, commit 777b420, commit b9670c1(19 Dec 2019), and commit c5c4edd, commit 072a231, commit 2f5d384, commit a2b1336, commit 452efd1(10 Dec 2019) by Elijah Newren (newren).
(Merged by Junio C Hamano -- gitster--in commit d2189a7, 25 Dec 2019)

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

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.

Revert "dir.c: 使 ' git-status --ignored' 在前导目录中工作"

签字人: Elijah Newren

提交be8a84c52669(" [dir.c ](https://github.com/git/git/blob/a2b13367fe55bdeb10862f41aff3e2446b63e171/dir.c): 使 ' git-status --ignored' 在领先目录中工作", 2013-01-15, Gitr合并)指出

git status --ignored <SOMEPATH>

<SOMEPATH>如果<SOMEPATH>未跟踪,则不会列出被忽略的文件和目录,并修改行为以使其显示它们。

然而,它是通过破坏一致性的黑客实现的。它会显示<SOMEPATH>不同于简单的路径

git status --ignored | grep <SOMEPATH>

会给他们看。

正确的修复稍微复杂一些,并且由于这个 hack 稍微复杂,所以我们恢复这个提交(但保留测试用例的更正版本),稍后将使用后续补丁修复原始错误。

一些历史可能会有所帮助:

提交 48ffef966c76(" ls-files: fix overeager pathspec optimization", 2010-01-08, Git v1.7.0-rc0 -- merge) 中提出了一个与我们正在恢复的提交非常相似的情况;但它实际上朝着相反的方向发展。

在那个提交中,它提到了如何

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

用于在t/即使t/被忽略的情况下显示未跟踪的文件,然后更改行为以停止在被忽略的目录下显示未跟踪的文件。

更重要的是,此提交考虑保留此行为,但指出当指定多个路径规范并因此拒绝它时,这将与行为不一致。

当一个路径规范被指定为零或两个时,整个不一致的原因是因为路径规范的公共前缀是通过一组不同的检查(in treat_leading_path())发送的,而不是正常的文件/目录遍历(那些通过read_directory_recursive()treat_path())。

因此,为了一致性,需要检查两个代码路径是否产生相同的结果。

还原提交 be8a84c526691667fc04a8241d93a3de1de298ab,除了删除它添加的测试用例之外,修改它以检查正确和一致的行为。

And:

和:

dir: fix checks on common prefix directory

Signed-off-by: Elijah Newren

Many years ago, the directory traversing logic had an optimization that would always recurse into any directory that was a common prefix of all the pathspecs without walking the leading directories to get down to the desired directory.

Thus,

git ls-files -o .git/                        # case A

would notice that .git/was a common prefix of all pathspecs (since it is the only pathspec listed), and then traverse into it and start showing unknown files under that directory.

Unfortunately, .git/is not a directory we should be traversing into, which made this optimization problematic.

This also affected cases like:

git ls-files -o --exclude-standard t/        # case B

where t/was in the .gitignorefile and thus isn't interesting and shouldn't be recursed into.

It also affected cases like:

git ls-files -o --directory untracked_dir/   # case C

where untracked_dir/is indeed untracked and thus interesting, but the --directoryflag means we only want to show the directory itself, not recurse into it and start listing untracked files below it.

The case B class of bugs were noted and fixed in commits 16e2cfa90993("read_directory(): further split treat_path()", 2010-01-08) and 48ffef966c76("ls-files: fix overeager pathspec optimization", 2010-01-08, Git v1.7.0-rc0 -- merge), with the idea being that we first wanted to check whether the common prefix was interesting.

The former patch noted that treat_path()couldn't be used when checking the common prefix because treat_path()requires a dir_entry()and we haven't read any directories at the point we are checking the common prefix.

So, that patch split treat_one_path()out of treat_path().

The latter patch then created a new treat_leading_path()which duplicated by hand the bits of treat_path()that couldn't be broken out and then called treat_one_path()for the remainder.

There were three problems with this approach:

  • The duplicated logic in treat_leading_path()accidentally missed the check for special paths (such as is_dot_or_dotdotand matching ".git"), causing case A types of bugs to continue to be an issue.
  • The treat_leading_path()logic assumed we should traverse intoanything where path_treatment was not path_none, i.e. it perpetuated class C types of bugs.
  • It meant we had split logic that needed to kept in sync, running the risk that people introduced new inconsistencies (such as in commit be8a84c52669, which we reverted earlier in this series, or in commit df5bcdf83aewhich we'll fix in a subsequent commit)

Fix most these problems by making treat_leading_path()not only loop over each leading path component, but calling treat_path()directly on each.

To do so, we have to create a synthetic dir_entry,but that only takes a few lines.

Then, pay attention to the path_treatmentresult we get from treat_path()and don't treat path_excluded,path_untracked,and path_recurseall the same as path_recurse.

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

签字人: Elijah Newren

许多年前,目录遍历逻辑有一个优化,它总是递归到所有路径规范的公共前缀的任何目录中,而无需遍历前导目录以到达所需目录。

因此,

git ls-files -o .git/                        # case A

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

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

这也影响了以下情况:

git ls-files -o --exclude-standard t/        # case B

这里t/是在.gitignore文件中,因此不感兴趣,不应该被递归进入。

它还影响了以下情况:

git ls-files -o --directory untracked_dir/   # case C

whereuntracked_dir/确实没有被跟踪,因此很有趣,但是这个--directory标志意味着我们只想显示目录本身,而不是递归到它并开始在它下面列出未跟踪的文件。

在提交16e2cfa90993("read_directory():进一步拆分treat_path()“,2010-01-08)和48ffef966c76(“ ls-files:修复overeager pathspec优化”,2010-01-08,Git v1.7.0-rc0--合并中注意到并修复了案例B类错误),我们的想法是首先要检查公共前缀是否有趣。

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

因此,该补丁treat_one_path()treat_path().

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

这种方法存在三个问题:

  • 重复的逻辑treat_leading_path()不小心错过了对特殊路径的检查(例如is_dot_or_dotdot和匹配“ .git”),导致case A类型的错误继续成为问题。
  • treat_leading_path()逻辑假定我们要穿越intoanything其中path_treatment不path_none,也就是说,它延续C级类型的错误。
  • 这意味着我们有需要保持同步的拆分逻辑,冒着人们引入新不一致的风险(例如在提交 be8a84c52669 中,我们在本系列的前面恢复了,或者在提交 df5bcdf83ae 中,我们将在后续提交中修复)

通过treat_leading_path()不仅循环遍历每个前导路径组件,而且treat_path()直接调用每个组件来解决大多数这些问题。

为此,我们必须创建一个合成文件,dir_entry,但只需要几行代码。

然后,注意path_treatment我们得到的结果treat_path(),不处理,path_excluded,path_untracked,path_recurse一样path_recurse