git log
→ Overview of project history
git show
→ Information about Git objects such as commits
→ Move the HEAD
pointer
Working directory & index get updated to match the snapshot pointed at
→ Your project is back at the state in which it was when you made that commit
Before:
→ Move the HEAD
pointer
Working directory & index get updated to match the snapshot pointed at
→ Your project is back at the state in which it was when you made that commit
After:
With git log
With the ~
notation:
HEAD~
or HEAD~1
is the main parent of the commit HEAD
is pointing to
HEAD~2
is the main parent before that
HEAD~3
refers to the 3rd commit before the current commit
etc.
You move HEAD
with git checkout
:
git checkout <commit-hash>
This is great to look around, then go back to the “present” with:
git checkout main
Starting point:
Now, we move HEAD
to the commit 31fukv1
:
git checkout 31fukv1
HEAD
is not pointing at a branch anymore: it is pointing directly at a commit → detached HEAD state
Your files are back at their state when you created commit 31fukv1
You can look at your project at that point in its history, then go back to the “present” with:
git checkout main
And that’s that.
Now, when you are at commit 31fukv1
, maybe you want to try something
But when you come back to “the present”, those experiments will get lost
So what if you want to keep those changes?
Here is what happens if you make a commit:
You can make more commits:
The thing is that you are still in this detached HEAD state. HEAD
is not pointing to a branch as it normally is.
Is this a problem?
It becomes a problem if you checkout main
from there:
If you don’t care about those commits, all is good.
But if you want to keep them, this is a bad situation because those commits are now left behind: they are not in the history of any branch or tag.
This is bad for three reasons:
Those commits will not show when you run git log
, so it is easy to forget about them
It is not easy to go back to them because there aren’t any tag or branch that you can switch to
The garbage collection (which runs every 30 days by default) will delete commits which are not on any branch or tag. So you will ultimately loose them
Here is a proper workflow if you have created commits from a detached HEAD
state
First, create a new branch:
Only then can you safely checkout main
:
The commits 23f481q
and rthy7wg
are now on a branch. They are part of the project history, they will not get deleted. All is good.
What if you left commits behind (not on a branch)?
You can retrieve their hash by running:
git reflog
This tracks the position of HEAD
over time
You can then checkout the commit you care about (so you are going back to a detached HEAD
state):
git checkout <hash-abandonned-commit>
This puts you back into a situation where you can rescue the commit(s) by creating a branch
Do this as soon as possible