How to undo a public commit with git revert (Git & Dev Tools)
Learn How to undo a public commit with git revert (Git & Dev Tools) step by step with clear examples and exercises.
Why This Matters
Undoing a public commit is an essential skill for any developer, especially in collaborative projects where multiple developers contribute to the same codebase. When you make a mistake that needs fixing before others can use your code, it's crucial to have the ability to undo the changes efficiently and maintain the integrity of the project's history. In this lesson, we will explore how to undo a public commit using the git revert command in Git, a popular version control system among developers worldwide.
The Importance of Undoing Public Commits
Public commits are visible to everyone on a shared repository, making it crucial to correct mistakes promptly. The git revert command allows you to create a new commit that undoes the changes made by an earlier commit while keeping the original commit history intact. This is particularly useful when you need to fix a bug or revert a mistake in a public repository, ensuring that your collaborators can continue working without being affected by the issue.
Prerequisites
To follow this lesson, you should have basic knowledge of Git and its commands. If you're new to Git, we recommend starting with our lessons on Git Basics and Branching and Merging in Git.
Understanding Git Commands and Workflow
Before diving into the specifics of git revert, it's essential to have a solid understanding of Git commands and workflow, including concepts like commits, branches, merges, and pull requests. Familiarizing yourself with these topics will help you better understand how git revert fits into the larger picture of version control and collaboration.
Core Concept
The git revert command creates a new commit that reverses the changes made by an earlier commit. Here's a step-by-step guide on how to use it:
- Navigate to the repository containing the commit you want to revert:
cd /path/to/repository
- Identify the commit hash (SHA) of the commit you want to revert. You can find this by running
git logand looking for the commit message associated with the changes you want to undo:
git log
- Use the
git revertcommand followed by the commit hash:
git revert <commit-hash>
This will open a text editor where you can write a commit message for the new commit that undoes the changes from the original commit. Save and close the file to complete the process.
- Once the new commit is created, Git will automatically merge it with your current branch. You can verify that the changes have been reverted by checking the differences between the original and new commits using
git diff:
git diff <commit-hash>^..HEAD
Understanding the Revert Process
When you run git revert, Git creates a new commit that undoes the changes made by the specified commit. The new commit contains the opposite of the changes from the original commit, effectively reversing its effects. This new commit is added to your current branch, preserving the original commit history while also fixing the issue.
Worked Example
Let's consider a simple example where we have a repository with an initial commit containing a file named main.cpp. We make a mistake in the second commit and want to revert it:
$ git init
Initialized empty Git repository in /path/to/repository/.git/
$ echo "int main() { return 0; }" > main.cpp
$ git add .
$ git commit -m "Initial commit"
[master (root-commit) 358c2f6] Initial commit
1 file changed, 1 insertion(+)
create mode 100644 main.cpp
$ echo "int main() { return 1; }" > main.cpp
$ git add .
$ git commit -m "Broken commit"
[master 9f2a3b7] Broken commit
1 file changed, 1 insertion(+), 1 deletion(-)
$ git log
commit 9f2a3b7e48d206e5c8191f9f8e142081f6471c6a (HEAD -> master)
Author: Your Name <your.email@example.com>
Date: Wed Jan 12 15:30:00 2022 +0530
Broken commit
commit 358c2f64e97b04a8f7d7b88496e3bb209f298990 (origin/master, origin/HEAD)
Author: Your Name <your.email@example.com>
Date: Wed Jan 12 15:20:00 2022 +0530
Initial commit
To revert the broken commit, we'll use the git revert command with the commit hash:
$ git revert 9f2a3b7e48d206e5c8191f9f8e142081f6471c6a
This will open a text editor where we can write the commit message for the new commit that undoes the changes from the broken commit:
This is the commit message for reverting commit 9f2a3b7e48d206e5c8191f9f8e142081f6471c6a.
The revert will undo changes to main.cpp, including the change that returned 1 from the main function.
Save and close the file to complete the process. You can now verify that the changes have been reverted by checking the differences between the original and new commits using git diff:
$ git diff 9f2a3b7e48d206e5c8191f9f8e142081f6471c6a^..HEAD
diff --git a/main.cpp b/main.cpp
index 446a4c1..63b50a7 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1 +1 @@
-int main() { return 1; }
+int main() { return 0; }
Understanding the Revert Commit
The new commit created by git revert is a reverse commit, meaning it contains the opposite of the changes made in the original commit. When you run git log, you can see that the new commit has the same parent as the original commit but with an opposite set of changes:
$ git log
commit 62b3089e475a1c6d7f562a208384d9b43ff47640 (HEAD -> master)
Author: Your Name <your.email@example.com>
Date: Wed Jan 12 15:35:00 2022 +0530
Revert "Broken commit"
This reverts commit 9f2a3b7e48d206e5c8191f9f8e142081f6471c6a.
commit 9f2a3b7e48d206e5c8191f9f8e142081f6471c6a (origin/master, origin/HEAD)
Author: Your Name <your.email@example.com>
Date: Wed Jan 12 15:30:00 2022 +0530
Broken commit
commit 358c2f64e97b04a8f7d7b88496e3bb209f298990 (origin/master, origin/HEAD)
Author: Your Name <your.email@example.com>
Date: Wed Jan 12 15:20:00 2022 +0530
Initial commit
Common Mistakes
- Forgetting to specify the commit hash: When using
git revert, always make sure you provide the correct commit hash to ensure that the intended changes are undone.
- Not providing a clear commit message: Always write a clear and concise commit message when using
git revertso that others can easily understand why the changes were made.
- Mistakenly merging the new revert commit: After creating a new commit with
git revert, Git will automatically merge it with your current branch. Make sure you don't accidentally merge the new commit into another branch or feature branch, as this could cause conflicts and complicate your workflow.
- Not testing the changes: Before pushing the new revert commit to a shared repository, always test the changes locally to ensure they fix the intended issue and don't introduce new problems.
- Not considering alternative solutions: In some cases, revert commits might not be the best solution. If the original commit contains multiple unrelated changes, it may be more appropriate to split the commit into smaller, more manageable commits before reverting them.
Common Mistakes - Subheadings
- Forgetting to specify the correct commit hash
- Not providing a clear and concise commit message
- Merging the new revert commit incorrectly
- Failing to test changes locally before pushing
- Considering alternative solutions
Practice Questions
- How can you find the commit hash of a specific commit in a repository?
- What happens when you run
git revertwithout specifying a commit hash? - How do you verify that changes have been successfully reverted using Git?
- In the example provided, what would happen if you tried to merge the new revert commit into another branch or feature branch?
- What are some potential consequences of not undoing a public commit when necessary?
- What are some alternative solutions to reverting commits in Git?
- How can you split a large commit into smaller, more manageable commits in Git?
- When should you consider using
git rebaseinstead ofgit revert? - How can you handle conflicts that arise during the revert process in Git?
- What are some best practices for maintaining a clean and organized commit history in Git?
FAQ
Q: Can I revert multiple commits at once using git revert?
A: Yes, you can revert multiple commits by providing a range of commit hashes separated by a comma. For example: git revert ...
Q: What if I want to undo changes from the last n commits? How do I specify that in git revert?
A: You can use ^ (caret) to represent the parent commit of a given commit. To undo changes from the last n commits, you can use git revert HEAD~n, where n is the number of commits you want to revert.
Q: What happens if I try to revert a merge commit using git revert?
A: When you attempt to revert a merge commit, Git will automatically split the merge commit into individual parent commits and create separate reverse commits for each parent. This can result in a complex commit history, so it's essential to understand the implications before proceeding.
Q: Can I undo a public commit that was pushed to a remote repository without affecting other collaborators?
A: To revert a public commit while minimizing disruption to others, you should first create a new branch with the reverted changes and then merge it into the main branch using a merge request. This allows your collaborators to review and approve the changes before they are merged into the main branch.
Q: What if I've already pushed the public commit to a remote repository, but I want to undo it locally?
A: If you've already pushed the commit to a remote repository, you can still revert the changes locally using git revert. However, you will need to force-push your local changes to the remote repository using git push --force after reverting the commit. Be cautious when using --force, as it can overwrite other collaborators' work if they have made changes based on your original commit.
Q: What are some alternative solutions to reverting commits in Git?
A: Some alternatives to reverting commits in Git include:
- Squashing multiple commits into a single commit using
git squash - Interactive rebase (
git rebase -i) to modify or remove specific commits from the history - Cherry-picking specific commits and applying them to a different branch
- Using
git stashto temporarily save changes and apply them later when needed
- Q: How can you split a large commit into smaller