git - 未跟踪的文件已从本地目录中消失
问题描述
在我的项目中,我有一个.gitignore
文件,除其他外,它public
被列为未跟踪的文件夹(因此 public 不会出现在 Github 存储库中)。
前几天,我从 master 签出了一个单独的分支,并从.gitignore
.
当我将这个新分支推送到 Github 时,它运行良好,我可以看到public
新分支上的跟踪。
但是现在public
已经从所有其他分支中完全消失了,当然包括master。有没有人遇到过类似的问题?我敢肯定有人有,所以这可能是多余的,但我不知道用更好的方式来表达这样一个奇怪的问题。
解决方案
根据您所说的,这是完全正常的。
文件不会基于分支进行跟踪与未跟踪。分支,或者更准确地说,您的分支名称1完全不相关。但是,每个分支名称都会选择一个特定的提交,并且提交是相关的。一个提交,一旦做出,永远是一样的——但是分支名称会根据你告诉 Git 对它们做什么而移动,所以分支名称并不重要:重要的是提交。
当且仅当该文件当前位于 Git 的index中时,才会跟踪您在使用 Git 时使用的文件。 真正令人惊讶且有点令人费解的是,文件的可跟踪性甚至不是提交的属性。它往往由提交控制,因为我们使用git checkout
或提取git switch
提交。这会从该提交中填充 Git 的索引,这就是导致文件现在成为跟踪文件的原因。
您看到和使用的文件不在Git中。 这是真正的关键:当人们使用 Git 时,他们倾向于认为他们在工作树中的文件是“Git 文件”或“分支中的文件”或类似的东西。这是错误的。您使用的文件(工作树中的文件)可能是从提交中提取的。 存储在提交中的文件在 Git 中。git push
当您使用或 时,它们会从一个 Git 转移到另一个 Git git fetch
。 工作树中的文件不在 Git 中。
如果 Git 从提交中复制了一个文件,并将其放入您的工作树中,那么当您运行git checkout master
orgit checkout mybranch
或时git checkout c0ffee900d
,Git 会首先将该文件复制到 Git 的索引中。(假设所有这三个名称都选择了 commit c0ffee900d
。)所以现在该文件存在于三个位置(也许还有更多提交,但至少这三个):
- 该文件在提交中,您可以使用例如
git show c0ffee900d:public/foo.html
; - 该文件位于 Git 的索引中,您可以使用
git show :public/foo.html
; - 该文件在您的工作树中,您可以看到它,因为您的常规计算机程序会向您显示这些文件并使用它们。
但是假设你现在git checkout
有一些其他的提交。通过哈希 ID 或分支名称选择任何其他提交。假设这个其他提交没有将文件存储public/foo.html
在其中。Git 现在看到您正在从其中包含的某个提交转移到没有的public/foo.html
提交。所以Git:
:public/foo.html
从 Git 的索引中删除,并且public/foo.html
从您的工作树中删除
因为你告诉它。
1另请参阅“分支”到底是什么意思?分支 这个词是模棱两可的:有时人们用它来表示分支的提示提交,在这种情况下,提交本身是相关的,并且您通过使用分支名称找到它,所以从这个意义上说,您的分支名称很重要。但是明天,您可能会更改与分支名称关联的哈希 ID,这可能会改变一切。但是,您无法更改有关某个特定提交的任何内容,并且您始终可以使用其哈希 ID 获取该提交。
对于这一切你能做些什么
存储库c0ffee900d:public/foo.html
中仍然有 的副本。该副本与 commit 一样永久:只要提交在存储库中,该文件的副本也是如此。但是那个文件不再在你的工作树中,因为它被跟踪了——它在 Git 的索引中——你告诉 Git 切换到 commit ,或者你选择的任何其他提交哈希 ID,并且那个提交没有那个文件。c0ffee900d
badcafe
您可能希望回到拥有未跟踪文件的状态,并以这种方式保存它们。未跟踪的文件不会像这样被删除或改组。当然,未跟踪的文件也不在每个新提交中,也不会出现在克隆中,所以也许你不想让它们不被跟踪。或者,也许您希望它们在某些提交中而不是在其他提交中,并且当您检查其中一个其他提交时仍然可以将它们取回。
切换到其他提交后如何取回文件
只要任何给定的文件未被跟踪——不在 Git 的索引中——然后从这个提交切换到那个提交就不会删除它(尽管你会得到一个有趣的抱怨):
$ git rm --cached file
rm 'file'
$ git checkout HEAD^
error: The following untracked working tree files would be removed by checkout:
file
Please move or remove them before you switch branches.
Aborting
发生这种情况是因为当前提交(在我的情况下8969ef2
)和目标提交之间的差异bb2af52
需要删除 file file
. 我file
在 commit 中添加并提交了文件8969ef2
。
所以,我现在可以mv file file.keep
,git checkout HEAD^
和mv file.keep file
. bb2af52
现在,当我作为分离的 HEAD提交时,它是一个未跟踪的文件。
作为替代方案,我可以这样做:
$ git restore --staged file
$ git status
On branch master
nothing to commit, working tree clean
(这个特定git restore
的命令直接来自git status
,作为撤消我要提交的删除的建议。其他命令,例如git reset -- file
,也可以。)
$ git checkout HEAD^
Note: switching to 'HEAD^'.
You are in 'detached HEAD' state. You can look around, make experimental
...
HEAD is now at bb2af52 initial
我的结帐现已成功,但我的工作树中不再有文件file
(当然,Git 的索引中也没有)。8969ef2
现在我使用哈希 ID或分支名称取回它master
:
$ git restore --source master file
$ git status
HEAD detached at bb2af52
Untracked files:
(use "git add <file>..." to include in what will be committed)
file
nothing added to commit but untracked files present (use "git add" to track)
我的文件名为file
,作为未跟踪文件回到我的工作树中,从我选择的提交中复制出来。如果您没有 Git 2.23 或更高版本,请使用:
git show master:file > file
而不是
git restore --source master file
推荐阅读
- sql - 如何使用两个表进行sql查询
- android - 如何搜索蓝牙设备?
- asp.net-core - .Net Core - 在解决方案中引用另一个项目会阻止系统和其他依赖项被识别
- sql - 我可以使用 ODBC 连接在 Excel 中使用 Select DISTINCT 函数来避免导入重复的列条目吗?
- excel - Excel 2016:重复行填充 4 个重复数字的系列
- asp.net-mvc-4 - 使用 linq 跨多个表执行搜索
- python - 为什么 stdbuf 对 Python 没有影响?
- php - 如何在其他数据库表中使用一个选择更新数据
- azure - 无法使用 Azure PowerShell 注册 Microsoft.DataFactory
- matlab - 激光雷达到相机图像融合