Instead of traditional “undo” systems, Git has its own system with completely different terminology, which includes such terms like git clean, git rm, git reset and so on. Each of these commands has specific functions and is used for undoing changes on the local and public repositories.
Reviewing old commits¶
After having created a project history commits, it is possible to review all the commits in the history. The best tool for reviewing old commits is considered to be the git log. Each commit has its identifying hash, which is used for revisiting commits.
git log --oneline a3b2a21ad Crossword solver with Vue.js c54ce0237 New logic for crossword game 3acb8d0de Some changes in crossword logic de32112e3 Styling crossword table area
By default, git log displays only the commits of the selected branch. In order to view all the commits across all the branches, run git log --branches=* command. Use git branch command to visit other branches.
Viewing old revisions¶
If you want to view the state of the project before you start a new experiment, firstly you have to find the identifying hash of the revision you want to see. You can do this with the help of the git log command:
git log --oneline
If you execute the command above, you will get project history which looks something like this:
b7119f2 Changes in Scrabble Solver 234be24 Fixing search input bug b235bf4 Make some changes to solver.php 256a81c Create solver.php 3243e12 Initial changes
Use the git checkout command to view the commit that you want.
git checkout b235bf4
After this, you will have an opportunity to view the files, run tests and so on. Even if you edit files, you can be sure that the current state of your project won’t be lost, because everything that you do here won’t be saved in the repository. Execute git checkout master master command to go back to the current state of your project and continue developing.
git checkout master
Back the master branch, you can use git revert or git reset to undo any change you want.
Undoing a committed snapshot¶
There exist different ways to undo a commit. Let’s imagine our commit history looks like the following:
git log --oneline 863fa8e Making some improvements b235bf4 Make some changes to solver.php 256a81c Create solver.php 3243e12 Initial changes
Below we will use different methods to undo the 234be24 Make some improvements commit.
Undoing commits with git checkout¶
The git checkout command will checkout the previous commit, b235bf4, putting the repository in a state before the improvements commit happens. As a result of checking, the repository state will be "detached HEAD". Being in a detached state means that each new commit made will be orphaned when branches are switched back to an established branch. Orphaned commits are prepared for being deleted by Git garbage collector that runs on a configured interval permanently destroying orphaned commits. For avoiding this,make sure that you are on a branch. From the detached HEAD state of the repo, you can invoke git checkout -b new_branch_without_improvement_commit . Consequently, you will have a new branch named new_branch_without_improvement_commit and switch to that state. Now we have a new history timeline without the 234be24 commit. At this stage, when we no longer have the 234be24 commit, we can look at some undoing strategies.
Undoing a public commit with git revert¶
The git revert HEAD creates a new commit with the converse of the last commit and a new commit is being added to the current branch:
git log --oneline 23a4b42 Revert "Making some improvements" 234be24 Making some improvements b235bf4 Make some changes to solver.php 256a81c Create solver.php 3243e12 Initial changes
Now the 234be24 commit is again undone, although it is still there in the history, the new 23a4b42 commit is a reverse of the modifications in 234be24. Contrary to the previous checkout method, you can still use the same branch. This is the perfect 'undo' method for working with repositories that are shared publicly.
Undoing a commit with git reset¶
Git reset is a comprehensive command that has various uses and functions. Executing git reset --hard b235bf4, the commit history will be reset to that stated commit. At this point, invoking git log will show that the history looks like this:
git log --oneline b235bf4 Make some changes to solver.php 256a81c Create solver.php 3243e12 Initial changes
Undoing the last commit¶
Undoing strategies described above work equally on the last commit. But in some cases you won't need to remove or reset the most recent commit. It may be just done too soon. In such a case, you can amend that recent commit by executing git commit --amend, once more changes are made in the working directory and staged for commit with git add. At this point, Git will open the configured system editor letting you modify the last commit message. These new changes will be added to the altered commit.
Undoing uncommitted changes¶
Changes are in the staging index and the working directory before being committed to the repository history. So you may want to undo them from these two areas. In case you want more information about these two areas, consider git reset.
The working directory¶
The working directory represents the files on the file system of your computer, that are available to the code editor for applying changes. Git has some tools for managing the working directory, including git clean and git reset commands.
The staging index¶
The staging index is one of the trees of Git. It tracks the changes committed in the working directory. The command that adds changes to the staging area is git add. Here we can use git reset command for undoing changes. A --mixed reset pushes the changes from the staging index to the working directory.
Undoing public changes¶
The best way for undoing public changes is using git revert command. Never use git reset for this purpose, because it will remove the commits in the shared history. It is designed to undo local changes to the working directory and staging index. Git revert will save the commits you want to undo and will create a new commit instead of the one that you don’t need.