I was checking my commit history to fixing a bug.
I use
git checkout 4a3cf4ebfc8c3d4a7f8b055b3f38cc90acf2a0cd to Switching between commits.
I was in - 'detached HEAD' state.
in that state, I use some command like:
git add .
git commit -m "massage"
Then I Switch different commits by git checkout e255fb94e967c4c1463c25e44090bfc5a40b8463.
I return from 'detached HEAD' state by using the command: git checkout master.
Now, my .env file is gone from the local directory.
I am creating a react app. I am using .gitignore file to ignore my API key in .env file.
Given some particular conditions (which must be the case here), this is normal.
We start with these facts:
Git stores commits. Git does not store files, nor branches, but rather entire commits. (Each commit does store files, but you work with an entire commit at a time. Branch names help you—and Git—find commits, because the commit numbers are so random-looking.)
Each commit has a unique number, which looks random, but isn't: it's the commit's hash ID. The hash ID is actually a cryptographic checksum of the contents of the commit. No part of any commit can ever be changed.
Each commit actually stores two things: a snapshot—a complete set of all of your files—and some metadata. The entire commit is completely read-only, and all the files in the commit are stored in a read-only, Git-only, compressed and de-duplicated form.
This in turn means that you cannot actually work with the files inside a commit. The files that you see and work with are copied out of some commit, into an area Git calls your working tree or work-tree.
Hence the
git checkoutcommand, when given a name likemasteror a raw commit hash likee255fb94e967c4c1463c25e44090bfc5a40b8463, has to copy the files that are stored (forever) in that commit (but are not usable by programs like ReactJS) into your work-tree (where they are are usable by programs like ReactJS).This means that the files you see and work with, in your work-tree, are not actually in Git in the first place. They're just copies of files from some commit in Git.
Now, suppose that the last commit of your
masterbranch isa123456.... I made up hash ID, but we can be pretty sure that whatever the actual hash ID is, it's note255fb94e967c4c1463c25e44090bfc5a40b8463. So your Git has, inside it, as two different commits:e255fb94e967c4c1463c25e44090bfc5a40b8463: this commit has a.envfile in it.a123456...: this commit does not have a.envfile in it.When you check out commit
e255fb94e967c4c1463c25e44090bfc5a40b8463, Git must extract the saved.envfile to your work-tree.When you switch back to
a123456..., Git must remove that saved.envfile to get it out of the way.Unfortunately, the
.gitignorefile does not actually tell Git to ignore files. It can't: commite255fb94e967c4c1463c25e44090bfc5a40b8463has the.envfile in it, and no part of any existing commit can ever be changed.So, when you extract commit
e255fb94e967c4c1463c25e44090bfc5a40b8463, Git copies the.envfile out of that commit (into both Git's index or staging area, and your work-tree). If your.envfile has valuable data in it, this copying-out process could destroy the valuable data.Usually, when
git checkoutmight destroy the contents of a file, Git will warn you about this, and refuse to do thegit checkoutuntil you have saved those file contents elsewhere. Unfortunately, one of the side effects of listing a file in.gitignoreis that it sometimes (not always, but sometimes) gives Git permission to destroy the file's contents.Perhaps, though, the
.envfile contents you had that were in your work-tree, but not in commita123456..., matched the contents in commite255fb94e967c4c1463c25e44090bfc5a40b8463. If that was the case,git checkout e255fb94e967c4c1463c25e44090bfc5a40b8463left the contents in place, without actually destroying anything. Unfortunately Git will still remove the file when switching back, but you can, at this point, instruct Git to retrieve the contents of that one particular file from that one particular commit:for instance.