【问题标题】:Untracked files not shown in "git status"“git status”中未显示未跟踪的文件
【发布时间】:2011-06-04 09:04:29
【问题描述】:

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

所有项目文件都在base_fldr 文件夹中。另外,我在base_fldr 中有几个文件夹,分别称为sub_fldr1sub_fldr2。这些子文件夹还包含一些文件。

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

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

该文件或其扩展名不在我的.gitignore 列表中。另外,我确实尝试过git add sub_fldr\file_name,但它既没有给出错误也没有将文件添加到索引中。

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

【问题讨论】:

  • 运行git status -u时是否显示文件
  • 不,没有。 git status -u 在我的 base_fldr 中显示新添加的文件,而不是那些在 base_fldr\sub_fldr| 中的文件

标签: git status


【解决方案1】:

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

【讨论】:

  • sub_fldr里面没有.git目录
  • 如果您确实有一个 .git 子目录,则更改仍应显示在父目录中
  • 确保你设置了“显示所有文件”——这让我忙了几个小时。我确实有一个“.git”子目录,我看不到它。但是 Git 可以...
【解决方案2】:

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

git add base_fldr\sub_fldr\

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

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

【讨论】:

  • OP 说 sub_fldr 中的修改文件 显示在 git status 中。
  • 我的 base_fldr\sub_fldr\ 被跟踪。实际上,如果我修改现有文件 git status 正确地将 sub_fldr 中的文件显示为已修改。
【解决方案3】:

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

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

感谢大家的回复。

【讨论】:

  • 同样的事情发生在我身上,我终于意识到我实际上已经将几个月前创建的文件夹名称添加到了 .gitignore 文件中,没有明显的原因!但是这个答案 +1 让我检查它 ;-) ... 和 -1 让我在第一次检查之前搜索 StackOverflow
  • 命令,为了完整起见:git status -u --ignored
【解决方案4】:

这是该问题中描述的行为的另一个原因(git status untracked files list does not include an untracked file in a subfolder)。如果文件因为 .gitignore 文件而未被跟踪在子文件夹中,那么该文件将不会包含在 git status 未跟踪文件列表中。

【讨论】:

    【解决方案5】:

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

    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
    

    【讨论】:

      【解决方案6】:

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

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

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

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

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

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

      2 的输出中存在但1 的输出中不存在的任何文件由于.gitignore 文件中的某些标志而未显示为未跟踪

      【讨论】:

        【解决方案7】:

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

        commit 0aaf62bcommit defd7c7commit 8aaf8d7commit b07bc8ccommit 95c6f27commit 6cd5c58commit 46aa2f9commit 5bd8e2dcommit 5bd8e2dcommit be8a84c、@9876543321、@、@9876543321 @、commit 289ff55commit 560bb7a(2013 年 4 月 15 日)Karsten Blees (kblees)
        (由 Junio C Hamano -- gitster -- 合并到 commit 7093d2c,2013 年 4 月 23 日)

        dir.c: 让 'git-status --ignored' 在主要目录中工作

        签字人:Karsten Blees

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

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

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


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

        参见Junio C Hamano (gitster)commit 6836d2f(2019 年 12 月 20 日)。
        请参阅commit c847dfacommit 777b420commit b9670c1(2019 年 12 月 19 日)和commit c5c4eddcommit 072a231commit 2f5d384commit a2b1336commit 452efd1(2019 年 12 月 10 日)@9876543。 >(由 Junio C Hamano -- gitster -- 合并于 commit d2189a7,2019 年 12 月 25 日)

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

        签字人:Elijah Newren

        提交be8a84c52669 ("[dir.c](https://github.com/git/git/blob/a2b13367fe55bdeb10862f41aff3e2446b63e171/dir.c): 使'git-status --ignored'在主要目录中工作", 2013-04-15,Git v1.8.3-rc0 -- merge) 注意到

        git status --ignored <SOMEPATH>
        

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

        但是,它是通过破坏一致性的 hack 实现的;它会以不同于简单的方式显示&lt;SOMEPATH&gt; 下的路径

        git status --ignored | grep <SOMEPATH>
        

        会向他们展示。

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

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

        commit 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/ 被忽略,然后更改行为以停止在忽略的目录下显示未跟踪的文件。

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

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

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

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

        还有:

        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
        

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

        在提交16e2cfa90993 ("read_directory(): 进一步拆分treat_path()", 2010-01-08) 和48ffef966c76 ("ls-files: 修复过度的路径规范优化" , 2010-01-08, Git v1.7.0-rc0 -- merge),想法是我们首先想检查公共前缀是否有趣。

        前一个补丁指出treat_path() 在检查公共前缀时不能使用,因为treat_path() 需要dir_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() 逻辑假设我们应该遍历 path_treatment 不是 path_none 的任何地方,即它会导致 C 类错误持续存在。
        • 这意味着我们有需要保持同步的拆分逻辑,冒着人们引入新的不一致的风险(例如在commit be8a84c52669,我们在本系列的前面恢复了,或者在commit df5bcdf83ae,我们将修复在随后的提交中)

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

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

        那么,注意我们从treat_path()得到的path_treatment结果,不要把path_excluded,path_untracked,path_recurse都和path_recurse一样对待。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-10-30
          • 2013-04-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-08-31
          • 1970-01-01
          相关资源
          最近更新 更多