Git Concepts
What Even Is HEAD
?
HEAD
is a symbolic reference pointing to your current place in the git history. During normal state, this points to the latest commit on the branch you are on (the tip of the branch).
When in detached HEAD
state, HEAD
points to a specific commit SHA.
You can see what HEAD is currently pointing to by running
cat .git/HEAD
git enters detached head state when you:
- checkout a specific commit SHA
- checkout a remote branch without fetching first
git reflog
Is A Magical Time Machine
Background context
After finishing up a feature, passing review, and getting ready to ship to prod, I squashed a set of 7-ish commits and rebased onto main to clean up the branch.
Since this changes the git history, I forced pushed my changes into the remote, which forcefully replaced remote with my work.
Turns out something went wrong in my rebase and a test file for the feature I just completed (a days worth of work) had been deleted during the process. I had no copy of the commit introducing the test file in my local and no copy in the remote.
Turns out git reflog
was able to help me find the SHA of the commit where the test file was. I checked out that commit SHA and copied the test file into my squashed feature branch. I probably could have used git cherrypick
but that is a lesson for another day.
What is git reflog
The reflog is a log of all the moves HEAD
has made in your local repository. Every time you switch branches, start a rebase, merge branches, go into detached head state, etc. the reflog keeps an entry of this movement. Each entry includes the commit hash, and a message that contains a few other infos (like the branch name you switched to). This data is stored in your projects local .git
directory.
The reason why it’s possible to restore a messed-up repository with reflog is because git keeps those commit hashes. As long as there is some reference to a commit somewhere in the repo, Git won’t forget about that commit.
As long as you are following good commit practises - commiting often, committing atomically - it’s near impossible to have something be lost forever.
Just don’t delete your .git
directory, the reflof of all your local movements will NOT be in the remote repo.