In this article I will talk about the ways we have available to undo things when using git. I will tackle
git clean and
To better explain it, I would like to go to the basics about the three main sections we have on git, which are
- Git directory is where all the information regarding metadata and object is stored.
- The Index , also known as
staging area, is a file with information about what will go into your next commit.
- The working directory consist of files that you are currently working on.
These concepts are important, because the ways I will talk to undo changes might change different sections depending on how we use it. Any change on the working directory is considered a dangerous change, because if we delete something from the working tree that was not commited or added to stage yet, it will be lost.
For this article, I already have a repository with two files, a
README and a file named
add_new_file and I try to show how my repository is with the following image.
→ ls README add_new_file
The current context of
add_new_file is the following:
This is the new file I want to add. This is a new change
And the changes we can see using
git log add_new_file, which are:
→ git log add_new_file commit e03d1e99a9210a1fb6d26ceb1fce93f0e795f4a6 Author: Bruno Costa <email@example.com> Date: Sun Oct 1 11:42:10 2017 +0100 New change to the add_new_file commit c5c7ae474a94480530059017066ac6197d0a043b Author: Bruno Costa <firstname.lastname@example.org> Date: Tue Aug 22 23:35:39 2017 +0100 Add new file
I will add some text to the file
add_new_file and I will show you how you can undo that change without having to delete the change yourself.
Lets start with
git checkout. If you are using git, my guess is that you use this command often to checkout a branch to work on. This is where we use the
git checkout <branch> option, where
I will now add some text to the file
add_new_file, something like “Yet another change”.
→ git status On branch new_branch Your branch is up-to-date with 'origin/new_branch'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: add_new_file no changes added to commit (use "git add" and/or "git commit -a")
Now, if I wanted to revert those changes without manually deleting each change I did on the file, I could use the command
git checkout <path>. The
git checkout <path> does not switch branches, instead it is used to restore modified or deleled path from the index. Just type
git checkout add_new_file and check the status using
git status and you should see that those changes are now gone.
→ git status On branch new_branch Your branch is up-to-date with 'origin/new_branch'. nothing to commit, working directory clean
You probably also noticed that you were not asked to confirm the checkout. Please remember, this is a very dangerous command. As far as I know, there is no way to recover those changes using git.
git reset is used often and it’s one of those commands that can destroy work, because it affects the working tree. That said, please be careful with doing git reset with –hard option.
git reset –hard
Lets start by the option –hard. I know this is not the best option to start explaining
git reset , but since I just talked about
git checkout I think it would be good to start with –hard because given the same context we had on the git checkout example, the outcome will be the same.
git reset --hard in this context, the outcome will be the same as using
git checkout add_new_file, but we need to understand the internals. Instead of picking the change from Index, it will pick up from
HEAD and it will also replace what we may have on the
Index. Which means that if we had do
git add add_new_file it will also reset the content of add_new_file from Index.
git reset –mixed
This command is the default, which means, if we don’t add anything to the
git reset it will behave as
git reset --mixed.
For this example, lets consider that we add the change we did on the
If we do
git reset --mixed or
git reset it will replace the content we have on
Index, but it will not replace anything on the working directory.
git reset –soft
One thing I didn’t tell you is that you can indicate a commit to do the reset. That will first update the HEAD to the given commit and if we use
--soft it will be all that it would do.
Summing up, it will first update the HEAD to the given commit, if
--mixed it will also update the
Index or it will also update the working directory if we use
This command is useful to remove those files that are not tracked, as an example, we can imagine adding a wrong file and we want to clean up the working directory. We can also use
-x option to remove those files that are ignored (.gitignore), which is useful to remove
bin folders for example.
Last, but not least,
git revert. All the options we’ve looked at so far just erase changes we did, without recording the action itself. This command is different, this command allows us to revert changes already committed, without changing the history of repository, but adding a new commit with the revert.
I can think of one good reason to use this command, imagine that we introduce a change with performance issues. We want to revert that change, but we want to keep that revert in our repository, to explain why we did it and because the history should tell the life story of a repository. However, if we find ourselves using
git revert too often before a release, we might need to change our workflow.
I will use the revert to remove the changes I did on commit
git revert e03d1e9 and it will ask me for a commit message and I will use something like
Revert "New change to the add_new_file" After starting the canary release, we started noticing some performance issues with this change. This reverts commit e03d1e99a9210a1fb6d26ceb1fce93f0e795f4a6.
After I save it, if I go to
git log I will see my new commit there.
→ git log --pretty=format:"%h %an: %s" 0dbcaef Bruno Costa: Revert "New change to the add_new_file" e03d1e9 Bruno Costa: New change to the add_new_file c5c7ae4 Bruno Costa: Add new file de4fc88 Bruno Costa: Add README
Trying to translate it into an image, it would be something like this:
I hope you enjoyed the article, if you have any questions or suggestions, feel free to comment. Thanks!