Cookbook: How to Effectively Revert a Git Commit
3 min readAs a software engineer, encountering situations where recent changes need to be undone is not uncommon. It may be due to errors, or in some cases just need a significant rework. When such scenarios arise while using Git as your version control system, there’s a few approaches that can help revert those changes effectively.
Let’s take a closer look.
The Cookbook
1. Simply revert it
This is the most straightforward method to undo changes in a Git repository. This command generates a new commit that reverses the changes made by previous commits, without erasing the history.
git revert [commit-hash]
Note that if the commit you're reverting has led to conflicts with the current state of your project, Git will prompt you to resolve these conflicts manually. Also it’s not the most efficient method for reverting a series of commits in quick succession.
2. Rewind to a specific state
For scenarios that calling for a more aggressive approach, it allows you to rewind the project's history to a specific state, discarding commits entirely.
There're three different way to "reset":
- Soft reset: Keeps changes in your staging area.
git reset --soft [commit-hash]
- Mixed reset: Unstages changes, leaving them in your working directory.
git reset [commit-hash]
- Hard reset: Discards all changes since the commit, reverting the working directory to the specified state.
git reset --hard [commit-hash]
It truly offers a quick method to reverse multiple commits. However, its potential for destructiveness, especially with the --hard
option, carries the risk of erasing previous work. Moreover, it might not be appropriate for shared branches since it alters the history, potentially interfering with the work of others.
3. New Branch
If the changes are experimental or you're unsure about immediately discarding them, creating a new branch from a previous commit can be a prudent approach.
# First check out the commit
git checkout [commit-hash]
# Then create a new branch from there
git checkout -b [new-branch-name]
This approach appears simple and straightforward; when used correctly, it also proves to be very powerful. It is widely regarded as a safeguard for the current state of the project, enabling risk-free experimentation. Meanwhile, it maintains the cleanliness of the main branch, offering the flexibility to explore various solutions.
It's important to note that because this method necessitates the management of additional branches, some housekeeping may be required to ensure the repository remains organized.
On the downside, what it cannot resolve is the need to address issues directly in the mainline branch.
4. Rebase
Rebase is a powerful and interactive tool for editing a series of commits, allowing you to modify, squash, or drop commits entirely. Senior engineers can tell you that it is sometimes ideal for cleaning up commit history before merging feature branches.
git rebase -i [commit-hash]^
It is considered disruptive approach as well, meaning it has the potential to disrupt the shared history, complicating collaboration. So a good understanding of Git is needed in this one to avoid pitfalls.
Summary
When deciding which strategy to employ, consider the nature of the changes, the state of collaboration within the repository, and the potential impact on the project's history. In collaborative environments, opt for methods that preserve history (git revert) or ensure you're working on isolated branches. For local cleanup or when working solo, more aggressive tactics like git reset or interactive rebase may be suitable. Always double-check before executing commands that could alter history, especially in shared repositories.