未跟踪的文件未显示在git状态中

时间:2011-01-06 00:10:04

标签: git status

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

所有项目文件都在base_fldr文件夹中。另外我在base_fldr中有一些名为sub_fldr1和sub_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,但既没有给出错误,也没有将文件添加到索引中。

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

7 个答案:

答案 0 :(得分:22)

答案 1 :(得分:15)

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

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

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

git status -u --ignored

我花了一段时间才弄清楚发生了什么,但我只需要用以下方法撤消命令:

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

答案 2 :(得分:14)

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

git add base_fldr\sub_fldr\

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

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

答案 3 :(得分:8)

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

答案 4 :(得分:4)

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

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

  1. git ls-files --other --directory --exclude-standard
  2. 这将显示所有未跟踪的文件,同时遵守.gitignore文件。

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

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

      2的输出中存在但1的输出中没有的任何文件,由于.gitignore文件中的某些标记

      而未显示未跟踪的文件

答案 5 :(得分:2)

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

答案 6 :(得分:0)

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

请参见commit 0aaf62bcommit defd7c7commit 8aaf8d7commit b07bc8ccommit 95c6f27commit 6cd5c58commit 46aa2f9,{{3} },commit 5bd8e2dcommit be8a84ccommit c94ab01commit 184d2a8commit 0104c9ecommit 289ff55(2013年4月15日)作者:commit 560bb7a。 br /> (由Karsten Blees (kblees)Junio C Hamano -- gitster --中合并,2013年4月23日)

  

commit 7093d2c:在主要目录中使用“ git-status --ignored”功能

     

签名人:Karsten Blees

     

'dir.c'不会列出'path'的某些部分被归类为未跟踪的'path'内被忽略的文件和目录。

     

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

     

作为副作用,这也消除了在每个主要目录级别进行递归目录扫描的情况,因为从treat_directory()调用read_directory_recursive()时无法再调用treat_leading_path()


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

请参见git status --ignored path/commit 6836d2f(2019年12月20日)。
请参见Junio C Hamano (gitster)commit c847dfacommit 777b420(2019年12月19日)和commit b9670c1commit c5c4eddcommit 072a231commit 2f5d384,{ {3}}(2019年12月10日)通过commit a2b1336
(由commit 452efd1Elijah Newren (newren)中合并,2019年12月25日)

  

Junio C Hamano -- gitster --:使'git-status --ignored'在主要目录中工作”

     

签名人:伊利亚·纽伦

     

提交commit d2189a7(“ [ dir.c ](https://github.com/git/git/blob/a2b13367fe55bdeb10862f41aff3e2446b63e171/dir.c):将'{{1} }'在主要目录中工作”,2013-04-15,Git v1.8.3-rc0-Revert "dir.c)指出

git-status --ignored
     如果未跟踪git status --ignored <SOMEPATH>

将不会列出<SOMEPATH>中被忽略的文件和目录,并且修改了行为以使其显示。

     

但是,它是通过破坏一致性的黑客行为来实现的;它将在<SOMEPATH>下显示的路径与简单显示的路径不同

<SOMEPATH>
     

将显示它们。

     

涉及到正确的修复程序,并且由于此hack稍微复杂一些,因此我们还原了该提交(但保留了测试用例的正确版本),以后将通过后续补丁修复原始错误。

     

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

     

be8a84c52669中提出了与我们正在还原的提交非常非常相似的情况(“ git status --ignored | grep <SOMEPATH> :修复了过度的路径规范优化”,2010-01-08,Git v1.7.0-rc0- -merge);但实际上却是相反的方向。

     

在该提交中,它提到了方式

ls-files
     

用于在git ls-files -o --exclude-standard t/ 下显示未跟踪文件,即使t/被忽略,然后将其更改为停止在被忽略目录下显示未跟踪文件的行为。

     

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

     

指定一个路径规范而不是零或两个时,会出现整体不一致的原因是,路径规范的公共前缀是通过与正常的文件/目录遍历(通过这些遍历)不同的一组检查(在t/中发送的)发送的treat_leading_path()read_directory_recursive())。

     

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

     

还原commit 48ffef966c76,除了不删除它添加的测试用例外,还可以对其进行修改以检查正确和一致的行为。

并且:

  

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

     

签名人:伊利亚·纽伦

     

许多年前,目录遍历逻辑进行了优化,可以始终递归到所有路径规范的通用前缀的任何目录中,而无需先行到达目录即可到达所需目录。

     

因此

treat_path()
     

会注意到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 确实是未跟踪的,因此很有趣,但是untracked_dir/标志意味着我们只想显示目录本身,而不是递归到该目录中,并开始在其下面列出未跟踪的文件。

     

在提交commit be8a84c526691667fc04a8241d93a3de1de298ab --directory中记录并修复了案例B类错误:进一步拆分了("read_directory()“”,2010-01-08)和dir(“ { {1}}:修复过度的路径规范优化”,2010年1月8日,Git v1.7.0-rc0-16e2cfa90993),其思想是我们首先要检查公共前缀是否有趣。 / p>      

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

     

因此,该补丁将treat_path()dir_entry()中分离出来。

     

随后的补丁程序创建了一个新的treat_one_path(),它手工复制了无法分裂的treat_path()的位,然后将其余部分称为treat_leading_path()

     

此方法存在三个问题:

     
      
  • treat_path()中重复的逻辑意外漏掉了对特殊路径的检查(例如treat_one_path()和匹配的“ treat_leading_path()”),从而导致案例A类型的错误继续成为问题。
  •   
  • is_dot_or_dotdot逻辑假设我们应该遍历path_processing不是path_none的任何地方,即,它使C类错误永久存在。
  •   
  • 这意味着我们需要保持同步的分裂逻辑,冒着人们引入新不一致的风险(例如我们在本系列前面的48ffef966c76merge中引入了新的不一致之处)我们将在以后的提交中修复)
  •   
     

通过使.git不仅遍历每个引导路径组件,而且直接在每个前导路径组件上调用treat_leading_path()来解决这些问题。

     

为此,我们必须创建一个合成的treat_leading_path(),但这只需要几行。

     

然后,请注意我们从treat_path()获得的dir_entry,结果,不要将path_treatment treat_path()path_excluded,与{{ 1}}。