Git

Git Undo Commit Example

1. Introduction

Every human being may make mistakes, especially the Software developers:) When we’re writing code, it’s a process of how we’re thinking and how we solve specific problems. In real life, it could be a disaster if we make some irrecoverable mistakes. However, this will not happen in writing code for the developers, especially with the help of Git.

In this article, we will focus on how to revert what we have done to the previous status. This may  be caused by that we have made wrong update to our code, or we have deleted the existed code by accident, or even it could be you made some inappropriate comments to the code. This could be really awful if we don’t have ways to solve it. However, Git undo command makes this easy to recover to the previous version of the code. So you don’t need to worry about what you’ve done.

2. Git undo examples

2.1 Introduction on git directory

Before we dig into the Git undo commit operations, we need to have a general idea on the three different directories that a git system has: workspace, index/staging area and the local repository. The whole structure could be referred to the following figure, this figure comes out of the link on it. Detailed information could be found in this link. It’s a great article for beginners on git.

git repository
Git repository

To understand further of Git, we need to be very clear about the directories.

  • Workspace: it’s the place where you see in your computer system, or the directory where you check out your files. Files in the workspace could be added to the Git by using git add command.
  • Index: it’s also called stating area. It’s an invisible space where you can add files that you want to commit. To add commit, you can use git commit command.
  • Local repository: it’s also an invisible repository. Actually it’s stored in the .git folder, which is hidden in the folder you created.
  • Remote repository: this could be another computer, or it could be the server of others, such as Github, which we can consider it as a remote repository. To access to the remote repository, git push or git pull could be used

Here, we also need to get familiar with the concept of head, which is the pointer to the most recent commit on the current branch. It’s actually a hash value of current commit, which is calculated by SHA-1 hash on a file with a hash value of 160 bits that uniquely identifies the contents of the file.

2.2 Create git folder

To get started, we need to create a git repository firstly. So we go ahead and create a folder on our local machine with the name of GitLearning. Then we initialize the folder to make it a git repository with command git init. After this, you’ve created an empty git repository successfully. Wonderful!

The whole process and the command is shown below:

WXMs-MacBook-Pro:~ WXM$ cd Documents/
WXMs-MacBook-Pro:Documents WXM$ cd GitLearning/
WXMs-MacBook-Pro:GitLearning WXM$ ls
WXMs-MacBook-Pro:GitLearning WXM$ git init
Initialized empty Git repository in /Users/WXM/Documents/GitLearning/.git/
WXMs-MacBook-Pro:GitLearning WXM$ ls -ah
.	..	.git

Note that ls -ah is needed to make the .git folder visible. Otherwise, it can not been seen, and this is for security. If you change the content in .git folder, the whole git repository would be crush.

Then we create a empty txt file named README.txt. This is normal for software developers and also useful for others to check the usage of the code. So don’t forget to create readme file along with you code. After this, you can add any content into the txt file. For example, here we add a sentence with “This is a readme file.” in the file. To make it a real file in git system, we need to use git add and git commit commands, to add the file into the staging area and local repository, respectively. The whole procedure could be checked by the command below:

pcp352933pcs:GitLearning WXM$ vi READMEFILE.txt
pcp352933pcs:GitLearning WXM$ ls
READMEFILE.txt
pcp352933pcs:GitLearning WXM$ git add READMEFILE.txt 
pcp352933pcs:GitLearning WXM$ git commit -m "First time writing readme file"
[master d907151] First time writing readme file
 1 file changed, 1 insertion(+)
 create mode 100644 READMEFILE.txt

In the bash above, git add READMEFILE.txt add the READMEFILE.txt into the stating area, while the git commit -m “First time writing readme file” command add the READMEFILE.txt into the local repository.

Then if I run git status command to check the status of my git system, it shows that:

pcp352933pcs:GitLearning WXM$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)
nothing to commit, working directory clean

It shows that nothing to commit and working directory is clean. However, it also shows that your branch is ahead of ‘origin/master’ by 1 commit and use “git push” to publish your local commits. The reason for this is that I’ve connected this folder with my Github account, which is the remote repository. Because I haven’t add the file to the remote repository, so it will remind you of that. It also shows that using git push command it will publish the local changes to the remote repository. After running the git push, everything is good now:

pcp352933pcs:GitLearning WXM$ git push
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 309 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To https://github.com/******/GitLearning.git
   5a5a9ea..d907151  master -> master

Then when you check the status again, it’ll show you that everything works cleanly now.

pcp352933pcs:GitLearning WXM$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean

2.3 Git undo commit

In some cases, we want to change our minds and revert the commit we have made, then git makes this easy to operate on. This is called git undo commit.

To make this happen, we add another line to the READMEFILE.txt, with “Bad words for others”. Then we add the file to the stating area and to the local repository. The following is the process that we have done:

pcp352933pcs:GitLearning WXM$ git add READMEFILE.txt 
pcp352933pcs:GitLearning WXM$ git commit -m "Add bad words"
[master 1f50e80] Add bad words
 1 file changed, 1 insertion(+)
pcp352933pcs:GitLearning WXM$ cat READMEFILE.txt 
This is a readme file.
Bad words for others.

When we use git commit command it shows that 1 file changes, 1 insertion(+). That’s because we’ve added one line with “Band words for others”. Using the cat command to show where we’ve changed the file.

Again, git status could be used to check the status:

pcp352933pcs:GitLearning WXM$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)
nothing to commit, working directory clean

If we want to make sure what change we have made, then we could use git diff to check the difference between current version with the previous one. For git diff, more detailed instructions could be found in my other article about git diff example.

Then we add another line to the txt file with “I made changes again:)”. To check the difference, the following is how we do it:

pcp352933pcs:GitLearning WXM$ git diff
diff --git a/READMEFILE.txt b/READMEFILE.txt
index 4cc46cb..6b972f7 100644
--- a/READMEFILE.txt
+++ b/READMEFILE.txt
@@ -1,2 +1,3 @@
 This is a readme file.
 Bad words for others.
+I made changes again:)

Then we can see that the sentence with “+” shows that where we add content to the file.

Then if we made another change to the the txt file and add another line with “I love changing things.” Until now we’ve made three changes – adding three lines compared with the first version. The four commits are : Love making changes <- Made changes again <- Add bad words <- First time writing readme file, where the arrow shows the order of the changes.

In real life of development, thousands lines of code could be changed. We can not remember it rightly. So git log should be useful right now, and it’ll show all the change history we have made. We can try it with our own example here:

pcp352933pcs:GitLearning WXM$ git log
commit 67713e5af45b67aa2628b12a73d4b493a16de159
Author: Jun <wuxiaomin98@hotmail.com>
Date:   Wed Mar 30 17:19:12 2016 -0500

    Love making changes

commit 47640c18cf433c6f6c7ba26b34f886688d34a1d3
Author: Jun <wuxiaomin98@hotmail.com>
Date:   Wed Mar 30 17:18:38 2016 -0500

    Made changes again

commit 1f50e80eb551e3ed7981251378d4609e30248d2f
Author: Jun <wuxiaomin98@hotmail.com>
Date:   Wed Mar 30 16:58:21 2016 -0500

    Add bad words

commit d90715179d20e10c5d88fc8d8a58972605fb38c0
Author: Jun <wuxiaomin98@hotmail.com>
Date:   Wed Mar 30 16:32:28 2016 -0500

    First time writing readme file

The above file shows every change we’ve made with specific date and time. You should notice the long sequence of strings after the commit. That’s the commit id, which corresponds to specific commit. Why it’s not in 1, 2, 3… order? That’s because Git is a distributed system. If every commit id is in order, when multiple changes happen, there should be conflict.

Sometime, the changes are quite a lot and what we want is just to check the changes. Then git log --pretty=oneline could be utilized to show each commit in one line.

pcp352933pcs:GitLearning WXM$ git log --pretty=oneline
67713e5af45b67aa2628b12a73d4b493a16de159 Love making changes
47640c18cf433c6f6c7ba26b34f886688d34a1d3 Made changes again
1f50e80eb551e3ed7981251378d4609e30248d2f Add bad words
d90715179d20e10c5d88fc8d8a58972605fb38c0 First time writing readme file

See how convenient it could be!

Then if we want to go back to the previous version, git reset command could be used. What we use here is git reset --hard HEAD^. HEAD is means the commit of current branch. Symbol “^” means go back to the previous one version, “^^” means the previous two version and so on so forth. While it’s hard to continue with multiple “^” symbols when there’s hundreds and thousands versions. Then you can use the number directly. For example git reset --hard HEAD^ is the same as git reset --hard HEAD~1 and git reset --hard HEAD^^ is the same as git reset –hard HEAD~2. Pay attention to the symbol “~” before the numbers and do not forget to add it.

For our own example, right now the head is in 67713e5af45b67aa2628b12a73d4b493a16de159 Love making changes. If we want to go back to the previous version. Run the git reset --hard HEAD^ command and check the result.

pcp352933pcs:GitLearning WXM$ cat READMEFILE.txt 
This is a readme file.
Bad words for others.
I made changes again:)
I love changing things.
pcp352933pcs:GitLearning WXM$ git reset --hard HEAD^
HEAD is now at 47640c1 Made changes again
pcp352933pcs:GitLearning WXM$ cat READMEFILE.txt 
This is a readme file.
Bad words for others.
I made changes again:)

We can see from the above, that after we run the git reset command, it goes back to the previous version Made changes again. The 47640c1 is exactly the shortcut commit id for the previous commit.

Then if we want to go back to the initial status, we can go back twice with command git reset --hard HEAD~2

pcp352933pcs:GitLearning WXM$ git reset --hard HEAD~2
HEAD is now at d907151 First time writing readme file
pcp352933pcs:GitLearning WXM$ cat READMEFILE.txt 
This is a readme file.

Now job has done! Fantastic!

Then run git log, it shows only the first version.

pcp352933pcs:GitLearning WXM$ git log
commit d90715179d20e10c5d88fc8d8a58972605fb38c0
Author: Jun <wuxiaomin98@hotmail.com>
Date: Wed Mar 30 16:32:28 2016 -0500

First time writing readme file
pcp352933pcs:GitLearning WXM$ cat READMEFILE.txt
This is a readme file.

However, if one day we find that the lines we added are useful, could we go further and get it back? Yes, we can! If the terminal is not closed, we need to find the commit number which the version is. For example, the commit number for Love making changes version is 67713e5af45b67aa2628b12a73d4b493a16de159. Then we can use the git reset --hard command with the commit id following it. Note that we can use the first few numbers of the commit id in most case.

pcp352933pcs:GitLearning WXM$ git reset --hard 67713e5a
HEAD is now at 67713e5 Love making changes
pcp352933pcs:GitLearning WXM$ cat READMEFILE.txt 
This is a readme file.
Bad words for others.
I made changes again:)
I love changing things.

You see, it’s back. However, make sure you really want to go back and force. In some cases, if you don’t know the commit id, you won’t come back to the newest version.

In some cases, that you really want to come back to the newest version. Then git reflow could be useful for you, which will track every command you’ve made. Run the command and you’ll get something magic.

pcp352933pcs:GitLearning WXM$ git reflog
d907151 HEAD@{0}: reset: moving to HEAD^^^
67713e5 HEAD@{1}: reset: moving to 67713e5a
d907151 HEAD@{2}: reset: moving to HEAD~2
47640c1 HEAD@{3}: reset: moving to HEAD^
67713e5 HEAD@{4}: commit: Love making changes
47640c1 HEAD@{5}: commit: Made changes again
1f50e80 HEAD@{6}: commit: Add bad words
d907151 HEAD@{7}: commit: First time writing readme file

Here we have all the commit number to each commit and each reset/undo operation. So you don’t need to worry about where you’re now.

To make it more clear to understand, we can use the following figure to show how it work. The HEAD works as a pointer to point to specific version. For example, if HEAD is pointer to the last version. Then after using the reset command, we can go back the initial version.

git undo
Git head operation version 4

git undo1
Git undo operation to version 1

3. Conclusion

Git undo operation makes it quite easy for us to go back and force to different versions. If you get familiar with it, then it could be very powerful. However, please make sure that you know where you go to when you perform the undo operation. If not, you can make another branch to operate it, which will make your code more safe.

Jun Wu

Jun (Steven) Wu is a current Master student in Computer Science & Engineering department of University of Nebraska Lincoln (Lincoln, NE, USA). His current interests focus on Programming Languages (Java, Python), Relational Database (MySQL), NoSQL Database (Apache Cassandra, MongoDB), and Computer Networks.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button