DEV Community

Yair Mishnayot
Yair Mishnayot

Posted on

Let’s Learn Git Reset With Practical Example

Through our workflow with git as developers, we occasionally need to undo changes that we did to our code, and that is when we want to use git reset.

But, if I’m being honest, sometimes that can be confusing, and even scary, to use git reset. I used to find this command as a “black box” that I don’t know exactly what it does, but I do know that I’m scared that I might delete somehow parts of my code that I want to keep, or even somehow destroy the entire project.

In this post, we will take a look at git in general, and specifically git reset, to understand it. Because, like a lot of things in our life, we are afraid of what we don’t understand.

Note: This post was written assuming you have at least a basic familiarity with git and know basic commands of it.

How git works

We can think about git as a content manager that manages three trees:
1. The Head: points to our last commit.
2. The index: points to our next commit. After we use the “git add” command, the files we performed that command on are going to the staging area.
3. The working Directory(Working Tree): The place we work on our actual files in the project, before adding them to our stating area.

Note: The Head and the Index store their files inside the .git directory.

Basic Lifecycle

Usually, after adding a new file to our repository, we will have the following cycle:

  1. Make changes to our file.
  2. Stage our file.
  3. Commit our file.
  4. Push our file to our remote repository.

Step 1 is happening in the working tree. We made changes but did not stage those yet.

Step 2 is happening in the index tree. We staged the changes that we did, but we did not commit those yet.

step 3 is happening in the head tree. From there, we push those changes to our remote repository.

Using git reset

Now that we understand git better, we can continue to the git reset command. There are two parts to git reset:

1. The commit we go back to.
2. In which trees we want to keep our changes.

To get there, we get three “flags” for the git reset command:

  1. Soft: remove the changes from the head tree, and keep them in the index and the working directory trees.
  2. Mixed: remove the changes from the head and the index trees, and keep them in the working directory tree.
  3. Hard: remove the changes from all three trees.

So let’s look at an example. We have an initialized git repo, we created one file in the repo named file1.txt. When we run git status we get:

git status
On branch master
No commits yet
Untracked files:
(use “git add <file>…” to include in what will be committed)
file1.txt
nothing added to commit but untracked files present (use “git add” to track)
Enter fullscreen mode Exit fullscreen mode

Right now our file exists only in the working directory, but not in the index. It is “untracked”. Let’s add it to our index, and rerun git status:

git commit -m “our first file”
[master (root-commit) 7ed5dc0] our first file
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 file1.txt
git status
On branch master
nothing to commit, working tree clean
Enter fullscreen mode Exit fullscreen mode

As we can see after the last git status, there is nothing to commit. At this stage, all three trees are synced.

Now, let’s add another file to our directory named file2.txt, and we will go through the entire cycle again:

git status
On branch master
Untracked files:
(use “git add <file>…” to include in what will be committed)
file2.txt
nothing added to commit but untracked files present (use “git add” to track)

git add file2.txt

git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file:   file2.txt

git commit -m "added file 2"
[master 742c271] added file 2
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 file2.txt

git status
On branch master
nothing to commit, working tree clean
Enter fullscreen mode Exit fullscreen mode

We can see our two commits with git log:

git log
commit 742c2713887c8b0056bea68d32f542807dca2324 (HEAD -> master)
Author: Yair <yair543210@gmail.com>
Date: Wed May 25 22:39:34 2022 +0300
added file 2
commit 7ed5dc012974aa577184f71077d02ccc63653225
Author: Yair <yair543210@gmail.com>
Date: Wed May 25 22:34:23 2022 +0300
our first file
Enter fullscreen mode Exit fullscreen mode

Now let’s use git reset to go back to our first commit using the commit id. At first, we will try it without any flag:

git reset 7ed5dc012974aa577184f71077d02ccc63653225 // this is the first commit id
Enter fullscreen mode Exit fullscreen mode

Now let’s rerun git status:

git status
On branch master
Untracked files:
(use “git add <file>…” to include in what will be committed)
file2.txt
Enter fullscreen mode Exit fullscreen mode

When we ran git reset without any flag git used the mixed flag by default. Meaning the changes from our second commit were removed from the Head and the Index, but still stayed in the working directory. Let’s stage the changes again and commit them:

git add file2.txt
git commit -m “added file 2 again”
[master c211158] added file 2 again
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 file2.txt
Enter fullscreen mode Exit fullscreen mode

Ok. now when we run git log we will see only two commits, the first commit, and the second commit:

git log
commit c211158cee7a04c1cba4c7e10a2474c64b298d1c (HEAD -> master)
Author: Yair <yair543210@gmail.com>
Date: Wed May 25 23:42:56 2022 +0300
added file 2 again // this is the new commit
commit 7ed5dc012974aa577184f71077d02ccc63653225
Author: Yair <yair543210@gmail.com>
Date: Wed May 25 22:34:23 2022 +0300
our first file
Enter fullscreen mode Exit fullscreen mode

Now we will use git reset, but this time with the hard flag:

git reset — hard 7ed5dc012974aa577184f71077d02ccc63653225
HEAD is now at 7ed5dc0 our first file
git status
On branch master
nothing to commit, working tree clean
Enter fullscreen mode Exit fullscreen mode

When using the “hard” flag we deleted everything that was done after the commit we went back to. Because we created another file after that commit, that file is gone:

ls
file1.txt
Enter fullscreen mode Exit fullscreen mode

There is no file2.txt anymore.

Conclusion

Using git reset can be beneficial when we understand what it does. I highly recommend reading more about it and trying to use it in a safe environment like I just did in this tutorial. I truly believe that this is the best way to learn, by taking little examples.

This article was originally published at Medium

Top comments (0)