Git 拒绝跟踪某些文件(git add -f 不起作用)

Ewa*_*noy 3 git

我可能在不知不觉中误按了一些键,并触发了本地 git 存储库状态的奇怪变化,目前 git 拒绝跟踪某些文件。那是 :

如果我这样做git add -f myfile.txt,它会默默地执行并返回,但之后git ls-files -v myfile.txt当它应该返回时仍然不返回任何内容myfile.txt,并且git status仍然显示nothing to commit

有人建议问题可能与某些文件名太长有关,所以我尝试git config core.longpaths true在后面加上git add .git add -A

是的,我确实检查了该文件是否存在并且路径是否正确:file myfile.txt告诉我这是一个 ASCII 文本。

我还可以使用哪些其他 git 命令来更好地了解情况?

更新:在 的输出中git ls-tree -r HEAD,列出了我的文件,尽管略有修改:我myfile.txt上面简称的实际上是一个包含多个目录的长文件路径。中的对应条目git ls-tree -r HEAD是相同的路径,除了第一个目录不大写(我和 Unix 系统调用它,Depth_one但 git 调用它depth_one)。

tor*_*rek 5

TL;DR 摘要:这里的根本问题是案例折叠。您可能希望说服 Git 重命名所有文件。(Git 索引中的文件,又称临时区域,不在文件夹中,它们只是有很长的名称,似乎嵌入了文件夹名称。因此,您需要更改的名称都是以小写字母开头的名称“文件夹”字符串。)或者,使您的工作树与 Git 提交匹配:在 Git 中,文件名区分大小写。

\n

很长,有可重现的例子

\n
\n

更新:在 的输出中git ls-tree -r HEAD,列出了我的文件,尽管略有修改:我myfile.txt上面简称的实际上是一个包含多个目录的长文件路径。中的对应条目git ls-tree -r HEAD是相同的路径,除了第一个目录是大写的(我和 Unix 系统调用它,Depth_one但 git 调用它depth_one)。

\n
\n

这一点,以及您在 macOS\xe2\x80\x94 或较低级别上使用不区分大小写的文件系统 \xe2\x80\x94 的事实是关键项。我能够在我自己的 Mac 上重现您的问题,尽管重现器可能略有不同。(这类事情就是为什么最小可重现示例在这里如此重要。将问题简化到其核心是好的,但将其简化到消失的程度没有帮助!)

\n

为了重现该问题,我运行了:

\n
sh-3.2$ cd ~/tmp\nsh-3.2$ mkdir gitpath && cd gitpath && git init\nInitialized empty Git repository in /Users/torek/tmp/gitpath/.git/\nsh-3.2$ mkdir -p depth_one/depth_two\nsh-3.2$ touch depth_one/f1.txt depth_one/depth_two/f2.txt\nsh-3.2$ git add .\nsh-3.2$ git commit -m initial -m "" -m "commit with all lowercase names"\n[master (root-commit) 5462107] initial\n 2 files changed, 0 insertions(+), 0 deletions(-)\n create mode 100644 depth_one/depth_two/f2.txt\n create mode 100644 depth_one/f1.txt\nsh-3.2$ \n
Run Code Online (Sandbox Code Playgroud)\n

接下来,我们删除并重新创建该depth_one目录,而不告诉 Git,如下所示:

\n
sh-3.2$ rm -r depth_one\nsh-3.2$ mkdir Depth_one\nsh-3.2$ git status -s\nsh-3.2$ git status -s\n D depth_one/depth_two/f2.txt\n D depth_one/f1.txt\n
Run Code Online (Sandbox Code Playgroud)\n

这些D状态表明文件已丢失,这是事实。我们可以让他们回来git checkout,从 Git 的索引中提取它们:

\n
sh-3.2$ git checkout -- .\nsh-3.2$ git status -s\n
Run Code Online (Sandbox Code Playgroud)\n

此时查看 Git 认为索引/暂存区域中的内容很有用:

\n
sh-3.2$ git ls-files --stage\n100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0   depth_one/depth_two/f2.txt\n100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0   depth_one/f1.txt\n
Run Code Online (Sandbox Code Playgroud)\n

这里的哈希 ID 是空 blob 的哈希 ID。让我们将一些数据放入工作树副本中,Depth_one/f1.txt并使用它们的新名称Depth_one/depth_two/f2.txt使用新名称:

\n
sh-3.2$ git ls-files --stage\n100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0   depth_one/depth_two/f2.txt\n100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0   depth_one/f1.txt\n
Run Code Online (Sandbox Code Playgroud)\n

现在我们将一些数据放入工作树中重命名的目录中的f1.txt两个文件中。f2.txtGit 仍然认为名称都是小写的,并且因为我在这里使用的默认文件系统会进行大小写折叠,所以 Git\ 尝试使用名为的文件depth_one/f1.txtdepth_one/depth_two/f2.txt访问名称现在以Depth_one访问现在在实际工作树中。

\n
sh-3.2$ echo data for file one > Depth_one/f1.txt \nsh-3.2$ echo different data for file two > Depth_one/depth_two/f2.txt \nsh-3.2$ git status -s\n M depth_one/depth_two/f2.txt\n M depth_one/f1.txt\n
Run Code Online (Sandbox Code Playgroud)\n

短状态显示工作树副本已修改,但git add每个文件的显式状态的显式显示没有效果:

\n
sh-3.2$ echo data for file one > Depth_one/f1.txt \nsh-3.2$ echo different data for file two > Depth_one/depth_two/f2.txt\nsh-3.2$ git status -s\n M depth_one/depth_two/f2.txt\n M depth_one/f1.txt\n
Run Code Online (Sandbox Code Playgroud)\n

跑步git add Depth_one/也同样缺乏效果。然而有趣的是,git add .有所不同:

\n
sh-3.2$ echo data for file one > Depth_one/f1.txt \nsh-3.2$ echo different data for file two > Depth_one/depth_two/f2.txt \nsh-3.2$ git status -s\n M depth_one/depth_two/f2.txt\n M depth_one/f1.txt\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,完整的文件名仍然全部小写。要说服 Git 选择更改后的名称,只需删除索引条目,然后从头开始重新创建它们即可:

\n
sh-3.2$ git add Depth_one/f1.txt Depth_one/depth_two/f2.txt\nsh-3.2$ git status -s\n M depth_one/depth_two/f2.txt\n M depth_one/f1.txt\n
Run Code Online (Sandbox Code Playgroud)\n

(这里没有检测到重命名,因为旧文件是空的,新文件与空的旧文件有很大不同;但如果文件有实际内容,Git 会将它们显示为重命名)。

\n

(所有测试均使用 Git 2.20.1;我已经有一段时间没有更新这台 Mac 上的 Git 了。)

\n