给定一些特定条件(这里必须是这种情况),这是正常的。
我们从这些事实开始:
Git 存储提交。Git 不存储文件,也不存储分支,而是整个提交。(每个提交都存储文件,但您一次处理整个提交。分支名称可以帮助您——而 Git——<em>查找提交,因为提交编号看起来非常随机。)
每个提交都有一个唯一的数字,看起来是随机的,但不是:它是提交的哈希 ID。哈希 ID 实际上是提交内容的加密校验和。任何提交的任何部分都不能更改。
每个提交实际上存储了两件事:一个快照——所有文件的完整集合——和一些元数据。整个提交是完全只读的,提交中的所有文件都以只读、Git-only、压缩和去重的形式存储。
这反过来意味着您实际上无法使用提交中的文件。您看到和使用的文件从某个提交中复制到 Git 称为您的工作树或工作树的区域中。
因此,该git checkout
命令,当给定名称 likemaster
或原始提交哈希 likee255fb94e967c4c1463c25e44090bfc5a40b8463
时,必须将(永远)存储在该提交中的文件(但不能被 ReactJS 之类的程序使用)复制到您的工作树(它们所在的位置)可被 ReactJS 等程序使用)。
这意味着您在工作树中看到和使用的文件一开始实际上并不在Git 中。它们只是Git 中某些提交的文件副本。
现在,假设您的master
分支的最后一次提交是a123456...
. 我编造了哈希 ID,但我们可以很确定,无论实际的哈希 ID 是什么,它都不 e255fb94e967c4c1463c25e44090bfc5a40b8463
是. 所以你的 Git 在里面有两个不同的提交:
当您签出 commite255fb94e967c4c1463c25e44090bfc5a40b8463
时,Git 必须将保存的.env
文件提取到您的工作树中。
当您切换回 时a123456...
,Git 必须删除该保存.env
的文件以将其移开。
我正在使用 .gitignore 文件来忽略 .env 文件中的 API 密钥。
不幸的是,该.gitignore
文件实际上并没有告诉 Git 忽略文件。它不能:提交中e255fb94e967c4c1463c25e44090bfc5a40b8463
有.env
文件,并且任何现有提交的任何部分都不能更改。
因此,当您提取 commit 时e255fb94e967c4c1463c25e44090bfc5a40b8463
,Git 会将.env
文件从该提交中复制出来(到 Git 的index或staging area以及您的工作树中)。如果您的.env
文件中包含有价值的数据,则此复制过程可能会破坏有价值的数据。
通常,当git checkout
可能破坏文件的内容时,Git 会警告您,并拒绝这样做,git checkout
直到您将这些文件内容保存在其他地方。不幸的是,在其中列出文件的副作用之一.gitignore
是它有时(并非总是,但有时)授予 Git 销毁文件内容的权限。
不过,也许.env
您在工作树中但不在 commit 中的文件内容与commita123456...
中的内容匹配e255fb94e967c4c1463c25e44090bfc5a40b8463
。 如果是这种情况,git checkout e255fb94e967c4c1463c25e44090bfc5a40b8463
请将内容留在原处,而不会实际破坏任何东西。不幸的是,Git 在切换回来时仍会删除该文件,但此时您可以指示 Git 从该特定提交中检索该特定文件的内容:
git show e255fb94e967c4c1463c25e44090bfc5a40b8463:.env > .env
例如。