How Does Git Reset Work?
Want to know how the Git
reset option works?
In a series of Git courses on Envato Tuts+, I went through some of the fundamental concepts of Git in simple videos.
In this video from the series, you’ll learn all about Git reset. You’ll see how to use each kind of reset and how these varieties interact with the three Git trees:
- soft: only changes HEAD, but doesn’t change staged files in index or working files.
- mixed: moves HEAD and updates the index with the contents of the revision to which HEAD now points.
- hard: moves HEAD and updates the index and working directory—this is the only version of reset that can cause data loss.
I’ll also show you how to use
git reset on individual files.
Git Basics: Reset
How Git Reset Works
Git reset. What does it do? It's how you undo some changes that are local to your computer. When you have done some work that you need to rewind, reset is your friend. You can just start over. You can jump back and forth between the contents of various commits and do a bit of time traveling.
You have a few options at your disposal with git reset. You can go hard, soft, and mixed, and you can also operate and hold commit objects or do it at an individual file level.
Each of these three variations affect specific trees which git uses to handle your files and their contents.
How Git Reset Affects the Three Trees
Metaphorically speaking, every reset option changes a different tree, a different part of how git saves snapshots.
Trees, what are we talking about here? Git uses the working directory, the index (also known as the staging area), and something called HEAD for creating and for retrieving commits.
The working directory lets you change files that you can stage into the index. This staging area lets you fine tune and select what you want to put into your next commit. A commit object is a cryptographically hashed version of your contents. It has some added metadata and points back to previous commits which lets us do our time traveling bits.
HEAD is a reference that points to such commit objects. It is merely a pointer that updates with every new commit or change of branch. You can move it around and target any point in time with the commit object.
For more info about trees and such, have a look at my video about the three trees and Git. It covers the basic workflow in Git and is a solid basis to better understand the logic of using git reset.
The Different Reset Options Explained
Now let's look at the different options.
Git reset --hard
This goes the whole nine yards. It will first move HEAD and update the index with the contents of the commit HEAD is now pointing at. Then it will update the working directory with the contents of the index, thereby possibly destroying content you changed in the working directory.
Therefore, it is the only version of git reset that is a bit dangerous if you don't know what you are doing.
Git reset --mixed
This will move HEAD and also update the index with the contents of the desired commit that HEAD is not pointing at. The working directory is unaffected by that operation.
The mixed option is the default if you don't provide git reset with an option. It is always working directory safe, so no need to be afraid to lose your work.
Git reset ---soft
This option will only move HEAD and stops right there. In effect, this will undo the last git commit command.
The working directory and files that might be staged are still unaffected by that operation.
Using a File Path
With all these options for git reset, you specifically tell git where to stop replaying, rewinding the contents and files from previous commits to specify the trees you want to affect. We can take this a step further and program reset with a file path.
If you use a path, Git won't move HEAD. Why? Because HEAD points to a commit object, and it cannot point to only a subset of that. In other words, HEAD does not point to specific files but to commit objects, which consist of block files and some metadata. The index and working directory, on the other hand, can be addressed in slices of sorts.
Only the index and working directory play a role when you use a path. It simply copies the contents of a file into the index, and it cannot do much else.
git reset some-file.ext assumes that by default you meant
git reset --mixed HEAD some-file.ext and won't affect the working directory.
By the way, because HEAD cannot move, the soft option would be pointless. Let's say you've been working on version 3 of a file and added it to the index for your next comment. Now you want to unstage these changes. Run
git reset some-file.ext to unstage that particular file.
As a result, the index will be populated by the state of your file from version 2, the version from your last commit the commit HEAD is pointing at. The changes you made in your file, version 3 basically, are still available in the working directory. You're still able to get at these changes to stage version 3 of this file.
So what you do in effect with
git reset some-file.ext is you only manipulate the index.
Reset vs. Checkout
git reset --hard some-file.ext? Why can't we use that as well?
This functionality is accomplished by
git checkout with a filename.
git checkout some-file.ext is actually what
git reset --hard some-file.ext would do, but Git does not let us use the hard option.
Let's take this another step further. We can target any commit to reset a specific file, not just the most recent one represented by HEAD. This resets the targeted files in the index to the state of a certain commit, again without affecting the working directory or any commit.
After you've reset the index to the state of a certain commit, a backwards update of sorts, you can use
git checkout with a filename to check out the contents of the index into your working directory.
Why use checkout? Because
git reset --hard with a file is not something Git lets you do.
But be careful. Using
git checkout with a file path will get rid of your newest changes in your working directory and replace it with the version of the file in that specific commit.
Watch More Git Courses
If you found this useful, why not check out some more Git courses?
You could watch our Introduction to Git and GitHub or try the other Coffee Break Courses in this series:
- Git Basics: The Three Trees
- Git Basics: GitHub Pull Requests
- Git Basics: Branches
- Git Basics: States
- Git Basics: Merge and Rebase
Source: Tuts Plus