One of the most frequent tasks that developers have in their workflow is undoing a git commit. Git offers multiple ways to effectively undo commits without losing the work that has been done, such as fixing an error, going back to an earlier version, or just reorganizing the commit history. Knowing these methods can help maintain a clean and organized library and speed up the development process.
Depending on the user's needs and the commit stage that has to be undone, there are multiple ways in Git to undo a commit.
Checking the Git commit history is essential for tracking changes, evaluating how a project has evolved, and working productively with other developers.
For example, a file named file1 was modified in the directory to have a content "hello this is my file".
To show the changes made on the file, run the command below:
git status
A red text with a modified
prefix will show on the output to confirm that the file was modified.
The git status
command reports on the repository's current state and assists in monitoring the modifications' progress. It's a helpful tool to understand what's going on in the project before making any modifications. Git displays details about the files that have been edited, files awaiting the next commit, and files that are untracked.
The git log
can also be used to show the commit history of a repository. It shows the list of commits in chronological order, with the most recent commit coming at the top and the oldest at the bottom.
git log
This output shows the changes made on the file1 appearing from the most recent changes down to the initial commit done.
To reverse a commit that hasn't been pushed to a remote repository, use the git reset command. It enables "uncommitting" the modifications while preserving them in the working directory by shifting the HEAD
pointer to an earlier commit.
The changes committed in the example given above can be undone using the command below.
git reset --soft HEAD~1
This will roll back the commit and reset back to 1 point while maintaining the code modifications.
To see if the undo took effect, run the command below, this time a green with a modified
prefix will show on the output.
git status
The command's hard reset option will undo all the changes, including the code. Keep in mind that all modifications made with the --hard
option will be erased from the working directory, index (the staging area), and the local git repository. Therefore, consider carefully if you want to remove the changes from the working directory as well before using --hard
. However, git reset --hard
is a really useful tool for rapidly returning your project to a previous state. Run the commands below to do it.
git reset --hard HEAD~1
Compare the output of git log
command both before and after performing the undo. This is to confirm that the undo was successful.
Before:
After:
If no --soft
or --hard
option is used in git reset
, it will default to --mixed
. The git reset --mixed
command without additional parameters moves the HEAD
pointer to the previous commit and unstages the changes, leaving them in the working directory.
For example, changes were made in the repository by adding a new file named my_new_file and modifying the content of an existing file named git_revert_demo_file in the same repository. These changes were applied to the Staging index. The status of the changes can be verified using the command below:
git status
To rollback the changes, run the command below.
git reset --mixed
The output will show that the change is now Unstaged.
The Staging Index has been reset to a condition where git_revert_demo_file is the only file in the directory. This can be verified by running the git status
and git ls-files -s
command respectively.
git status
git ls-files -s
Using git reset --mixed
, you also can specify a particular commit to revert to via the HEAD~n
parameter where ~n
is the notation that specifies the Nth parent commit of the commit referenced by HEAD
.
In the below example, the working directory git_mixed_test has a file named sample_mixed_test_file with a content "hello git mixed test". The last commit made to the file is "Add content on the file". To verify, run the command git log
.
git log
To undo the change using git reset --mixed
, the parameter HEAD~1
will be used:
git reset --mixed HEAD~1
Use git log
again to view the changes done. Notice that the commit “Add content on the file” is no longer seen on the output.
git log
To reverse modifications made to a repository's commit history, use the git revert
command. Other "undo'" commands that shift the HEAD
and branch ref points to a certain commit include git reset
. Git revert
does not transfer reference points to a defined commit; instead, it accepts a specific commit. A revert operation takes a given commit, reverses its changes, and generates a new "revert commit". The new revert commit is then made the tip of the branch by updating the ref points to point at it.
In this example, there is already a repository created and named git_revert_directory. Three commits have been done to the repository (highlighted in yellow in the screenshot), where the file is named git_revert_demo_file. The contents of the file changed twice (box in red in the screenshot). To view the changes that have been made, run the command below.
git log
With the current state of repository, the git revert
can now be initiated. Run the command git revert <Hash>
. Hash comes after the word “commit” (boxed in blue in the example above).
git revert 3864b4b4cc81f2d4a648b5f8fff63586b948e1
This command will remove the added line, "prepend content to git_revert_demo_file" to the file git_revert_demo_file.
After running the git revert
command, a default editor will open to allow editing the commit description or leaving and saving it.
Git revert
does not work without a commit reference, which it expects to be handed in. Here, the HEAD
reference has been passed. HEAD
in this case is the commit related to “prepend content to git_revert_demo_file”.
Check the state of repository again and verify if revert took effect by running the command below:
git log
The revert word is shown in the output below (box in red in the screenshot).
Finally, validate the content of the file git_revert_demo_file. To view it, run the command below.
cat git_revert_demo_file
The output should show only the first changes that have been made, which is the content “First Content”. This will confirm that undo was successfully done.
The Git reflog (reference log) is a built-in mechanism that stores the history of reference updates in a Git repository. It records any changes to the tip of branches (e.g., commits, branch creations, branch deletions) and other references (e.g., tags, HEAD pointer) throughout time. Essentially, it's a chronological record of all reference pointer movements within the repository.
To view the reflog for the repository, run the command below.
git reflog show
This output contains a list of recent reference updates, as well as commit hashes and descriptions of the actions that resulted in the updates. Each entry in the reflog includes a reference to the commits before and after the update, making it simple to identify any changes that were lost or replaced. Run the command below to get a complete reflog of all refs.
git reflog show --all
To wrap it up, knowing how to undo Git commits is crucial for keeping your repository tidy and orderly, fixing issues quickly, and working well with other developers. By using these methods carefully and combining them with a deep knowledge of Git's workflow, a user can speed up the development process, reduce the chance of data loss, and guarantee the accuracy and integrity of your project's history.