问题描述
我正在检查提交历史以修复错误。
我用
git checkout 4a3cf4ebfc8c3d4a7f8b055b3f38cc90acf2a0cd
到在提交之间切换。
我在-'detached HEAD' state
。
在那种状态下,我使用一些命令,例如:
git add .
git commit -m "massage"
然后,我用git checkout e255fb94e967c4c1463c25e44090bfc5a40b8463
切换了不同的提交。
我使用命令git checkout master
从“分离的HEAD”状态返回。
现在,我的.env
文件从本地目录中消失了。
我正在创建一个React应用。我正在使用.gitignore
文件来忽略我在.env
文件中的API密钥。
解决方法
鉴于某些特殊条件(在这里必须是这种情况),这是正常的。
我们从这些事实开始:
-
Git存储 commits 。 Git不存储文件,也不存储分支,而是存储整个提交。 (每个提交确实存储了文件,但是您一次可以处理整个提交。分支名称可以帮助您和Git进行查找提交,因为提交编号看起来很随意。)
-
每个提交都有一个唯一的数字,看起来是随机的,但不是:这是提交的哈希ID。哈希ID实际上是提交内容的加密校验和。任何提交的任何部分都无法更改。
-
每个提交实际上存储着两件事:快照(文件的全部全部的完整集)和一些元数据。整个提交完全是只读的,并且提交中的所有 文件都以只读,仅Git,压缩和重复数据删除的形式存储。
-
这又意味着您实际上无法在提交内使用文件。您看到并使用的文件是从复制提交到某个区域,Git将该区域称为您的工作树或工作树。
-
因此,
git checkout
命令的名称为master
或原始提交哈希为e255fb94e967c4c1463c25e44090bfc5a40b8463
时,必须复制存储的文件(永远)中的提交(但不能被ReactJS等程序使用)进入您的工作树(其中 被ReactJS等程序使用)。
这意味着您最初在工作树中看到和使用的文件实际上并不是 in Git。它们只是Git中某些 commit 文件的副本。
现在,假设您的master
分支的最后一次提交是a123456...
。我组成了哈希ID,但是我们可以确定,无论实际的哈希ID是什么,它都是不是 e255fb94e967c4c1463c25e44090bfc5a40b8463
。因此,您的Git在其中包含两个不同的提交:
-
e255fb94e967c4c1463c25e44090bfc5a40b8463
:此提交中有一个.env
文件。 -
a123456...
:此提交中没有.env
文件。
当您检出提交e255fb94e967c4c1463c25e44090bfc5a40b8463
时,Git必须将保存的.env
文件提取到您的工作树中。
当您切换回a123456...
时,Git必须删除已保存的.env
文件,以使其摆脱干扰。
我正在使用.gitignore文件忽略.env文件中的API密钥。
不幸的是,.gitignore
文件实际上并没有告诉Git忽略文件。它不能:提交e255fb94e967c4c1463c25e44090bfc5a40b8463
中其中的.env
文件,并且任何现有提交的任何部分都无法更改。
因此,当您提取提交e255fb94e967c4c1463c25e44090bfc5a40b8463
时,Git将.env
文件从该提交中复制到Git的 index 或 staging区域 ,以及您的工作树)。如果您的.env
文件中包含有价值的数据,则此复制过程可能会破坏有价值的数据。
通常,当git checkout
可能破坏文件内容时,Git会警告您,并拒绝执行git checkout
,直到您将这些文件内容保存到其他位置为止。不幸的是,在.gitignore
中列出文件的副作用之一是它有时(并非总是,但有时)授予Git破坏文件内容的权限。
不过,也许您在工作树中拥有 的.env
文件内容而不是提交a123456...
中的文件内容与提交{{1 }}。 在这种情况下,e255fb94e967c4c1463c25e44090bfc5a40b8463
将内容保留在原位,而没有实际破坏任何内容。不幸的是,Git在回切时仍会删除文件,但是您可以在此时指示Git从该特定提交中检索该特定文件的内容:
git checkout e255fb94e967c4c1463c25e44090bfc5a40b8463
例如。