Checkout
The
git checkout
command is like a Git Swiss Army knife. Many developers think it is overloaded, which is what lead to the addition of thegit switch
andgit restore
commandsWe can use checkout to create branches, switch to new branches, restore files, and undo history!
We can use
git checkout <commit-hash>
to view a previous commit. We just need the first 7 digits of a commit hash which can be obtained throughgit log --oneline
. Doing so will result in a Detached Head. Now thegit log
will change because we have moved back in timegit checkout
supports a slightly odd syntax for referencing previous commits relative to a particular commit.HEAD~1 refers to the commit before HEAD (parent)
HEAD~2 refers to 2 commits before HEAD (grandparent
git checkout HEAD~1
Discarding Changes
Suppose you've made some changes to a file but don't want to keep them. To revert the file back to whatever it looked like when you last committed, you can use:
git checkout HEAD <filename>
to discard any changes in that file, reverting back to the HEAD.
Restore
git restore
is a brand new Git command that helps with undoing operations.git restore
was introduced alongsidegit switch
as alternative to some of the uses forcheckout
.Suppose you've made some changes to a file since your last commit. You've saved the file but then realize you definitely do NOT want those changes anymore!
To restore the file to the contents in the HEAD, use
git restore <file-name>
git restore <file-name>
restores using HEAD as the default source, but we can change that using the --source option.For example,
git restore --source HEAD~1 home.html
will restore the contents of home.html to its state from the commit prior to HEAD. You can also use a particular commit hash as the source.git status
will always remind you what to use!Unstaging Files with Restore
If you have accidentally added a file to your staging area with git add and you don't wish to include it in the next commit, you can use
git restore
to remove it from staging.Use the --staged option like this:
git restore --staged <file-name>
Git Reset
Suppose you've just made a couple of commits on the master branch, but you actually meant to make them on a separate branch instead. To undo those commits, you can use
git reset
.git reset <commit-hash>
will reset the repo back to a specific commit. The commits are gone but the changes will be kept in the working directory.If you want to undo both the commits AND the actual changes in your files, you can use the --hard option.
For example,
git reset --hard HEAD~1
will delete the last commit and associated changes.
Git Revert
git revert
is similar to git reset in that they both "undo" changes, but they accomplish it in different ways.git reset
actually moves the branch pointer backwards, eliminating commits.git revert
instead creates a brand new commit which reverses/undos the changes from a commit. Because it results in a new commit, you will be prompted to enter a commit message.The history of the commit is preserved but the changes are reverted
git revert <commit-hash>
Which Command To Use?
Both
git reset
andgit revert
help us reverse changes, but there is a significant difference when it comes to collaboration.If you want to reverse some commits that other people already have on their machines, you should use revert.
If you want to reverse commits that you haven't shared with others, use reset and no one will ever know!
Theory of Git Checkout
Usually, HEAD points to a specific branch reference rather than a particular commit. The HEAD is a pointer to the current branch reference and the branch reference is a pointer to the last commit made on a particular branch
When we make a new commit, the branch reference is updated to reflect the new commit. The HEAD remains the same because it's pointing at the branch reference. When you switch branches, HEAD is updated to point to the specific branch reference. This is all to say that HEAD usually refers to a branch NOT a specific commit.
When we checkout a particular commit, HEAD points at that commit rather than at the branch pointer
Detached Head
You have a couple of options:
Stay in detached HEAD to examine the contents of the old commit. Poke around, view the files, etc.
Leave and go back to wherever you were before - reattach the HEAD
git switch master
Create a new branch after checking out the old commit and switch to it. You can now make and save changes since HEAD is no longer detached.
Suppose you want to go back to an old commit and make some new changes
Checkout the old commit. Now in detached HEAD state.
While in detached HEAD, Make a new branch and switch to it. Head is now back to pointing at a branch reference!
Now on the new branch, make as many new commits as you want! It's like you time-traveled! We went back to an old commit and made a new branch based on it.
git checkout <d8194d6>
git switch -c newbranch
git add .
git commit -m "new commit"