Git Commit Revert: Tutorial and Examples
Git’s revert
command provides a safe way to undo changes introduced by a specific commit without rewriting history. Unlike reset
(which effectively “forgets” commits), revert
creates a new commit that reverses the effects of the targeted commit. This makes revert
the preferred method for undoing changes on branches shared with others, as it preserves the historical record and avoids causing conflicts for collaborators. This tutorial provides a detailed explanation and practical examples of using git revert
.
1. Understanding git revert
- What it does:
git revert <commit>
creates a new commit. This new commit applies changes that are the inverse of the changes introduced in the specified<commit>
. Think of it as automatically generating a “counter-commit.” - Why it’s important: Preserves history. It’s crucial for collaborative workflows because you aren’t erasing past work; you are adding a new commit that negates the old one.
- How it’s different from
git reset
:git reset
: Moves the branch pointer to a different commit, potentially discarding commits. Don’t usereset
on pushed commits that others might have based their work on!git revert
: Creates a new commit that undoes changes, leaving the original commit in the history.
2. Basic git revert
Usage
The fundamental command structure is straightforward:
bash
git revert <commit_hash>
Where <commit_hash>
is the SHA-1 hash of the commit you want to revert. You can find this hash using git log
.
Example:
Let’s say your git log
shows this (simplified):
“`
commit c1e5f8a9… (HEAD -> main)
Author: …
Date: …
Fix a minor typo
commit a8b7c6d5…
Author: …
Date: …
Introduce a bug (we want to revert this!)
commit f4d3e2c1…
Author: …
Date: …
Initial commit
“`
To revert the commit a8b7c6d5...
, you would run:
bash
git revert a8b7c6d5
Process after running git revert
:
- Editor Opens (Usually): Git will typically open your default text editor. This allows you to modify the default commit message for the revert commit. The default message will usually be something like “Revert ‘Introduce a bug (we want to revert this!)'”. You can change this message or leave it as is.
- Save and Close: Once you’re happy with the commit message, save the file and close the editor.
-
Revert Commit Created: Git will create a new commit. You can verify this with
git log
. You’ll now see a commit like:“`
commit d2e3f4g5… (HEAD -> main)
Author: …
Date: …Revert "Introduce a bug (we want to revert this!)" This reverts commit a8b7c6d5...
commit c1e5f8a9…
Author: …
Date: …Fix a minor typo
commit a8b7c6d5…
Author: …
Date: …Introduce a bug (we want to revert this!)
commit f4d3e2c1…
Author: …
Date: …Initial commit
``
a8b7c6d5…
Notice that the original commit () is still there, but a new commit (
d2e3f4g5…`) has been added to undo its changes.
3. Key git revert
Options
-
-n
or--no-commit
: This option stages the revert changes but doesn’t create a commit. This allows you to:- Inspect the changes: You can review what the revert would do before actually committing it. Use
git status
andgit diff
to examine the changes. - Combine with other changes: You can add other changes to the staging area and then create a single commit containing the revert and your additional modifications.
- Abort if necessary: If you decide the revert isn’t what you want, you can easily unstage the changes (
git restore --staged .
) without having to undo a commit.
“`bash
git revert -n a8b7c6d5 # Stages the revert, but doesn’t commit
git status # See the staged changes… make further changes or unstage …
git commit -m “Revert bug and add feature X” # Commit if you’re ready
“` - Inspect the changes: You can review what the revert would do before actually committing it. Use
-
-e
or--edit
(default): This is the default behavior. It opens your editor to let you edit the commit message. -
--no-edit
: This reverts the commit without opening the editor. Git will use the default revert commit message. Use this with caution, as you won’t have a chance to customize the message.bash
git revert --no-edit a8b7c6d5 -
-m parent-number
or--mainline parent-number
: This option is used when reverting a merge commit. Merge commits have multiple parents (one for each branch that was merged). You need to specify which parent represents the “mainline” – the branch you were on when you performed the merge. Typically, this is1
(the first parent).bash
git revert -m 1 <merge_commit_hash> # Revert a merge, keeping changes from parent 1
Without the-m
option, git revert on a merge commit will return an error such as “error: commit is a merge but no -m option was given.”
4. Reverting Multiple Commits
You can revert multiple commits in a single command by providing a range of commits:
bash
git revert <start_commit>..<end_commit>
This will revert all commits from <start_commit>
up to and including <end_commit>
. Git will create a separate revert commit for each commit in the range. It’s important to get the order right; Git processes the commits in reverse chronological order (newest to oldest).
Example:
Suppose you have commits A, B, C, D, and E (E being the newest). If you run:
bash
git revert C..E
Git will create three revert commits:
- A commit reverting E.
- A commit reverting D.
- A commit reverting C.
Important Note: Reverting multiple commits can lead to a lot of new commits. If you’re only trying to undo a few related changes, it might be cleaner to revert them individually or use -n
to combine the changes into a single revert commit.
5. Handling Merge Conflicts During Revert
Just like merging, reverting can sometimes lead to merge conflicts. This happens when the changes you’re trying to revert have been modified by subsequent commits.
Process for Resolving Conflicts:
- Git will report the conflict: You’ll see a message indicating which files have conflicts.
-
Open the conflicted files: The files will contain conflict markers (similar to merge conflicts):
“`
<<<<<<< HEAD
This is the current version.
=======
This is the version from the reverted commit.parent of
( )
“` -
Edit the files: Choose which version to keep (or combine parts of both). Remove the conflict markers (
<<<<<<<
,=======
,>>>>>>>
). - Stage the resolved files: Use
git add <file>
for each resolved file. - Continue the revert: Run
git revert --continue
. This will create the revert commit (and open your editor for the commit message, unless you used--no-edit
). - If needed,
git revert --abort
: If you get stuck or want to start over,git revert --abort
will cancel the entire revert operation.
6. Practical Examples
-
Scenario 1: Reverting a single, recent commit.
“`bash
git log # Find the commit hash of the problematic commit
git revertEdit the commit message (optional)
Save and close the editor
“`
-
Scenario 2: Reverting a commit without creating a new commit immediately.
“`bash
git revert -n
git status # Check the staged changes
git diff # Review the changes in detail(Optional) Make further changes
git commit -m “Revert changes and…” # Combine revert with other changes
“` -
Scenario 3: Reverting a merge commit.
“`bash
git log –graph –oneline # Find the merge commit hash and visualize the parents
git revert -m 1# Assuming parent 1 is the mainline Resolve conflicts if any
…
“`
-
Scenario 4: Reverting multiple commits.
bash
git log # Find the commit hashes
git revert <oldest_commit_hash>..<newest_commit_hash>
#Resolve any conflicts that may arise in each revert.
7. Best Practices
- Use
git revert
on shared branches: Always preferrevert
overreset
when working on branches that others are using. - Check changes with
-n
: Use--no-commit
to inspect the revert changes before committing them. - Write clear commit messages: Explain why you’re reverting the commit.
- Understand the implications of reverting merges: Be very careful when reverting merge commits, as it can significantly alter your history. Consider if reverting individual commits within the merge is a better approach.
- Test thoroughly: After reverting, always test your code to ensure that the revert had the desired effect and didn’t introduce new issues.
By following this tutorial and the provided examples, you should now have a solid understanding of how to use git revert
effectively and safely to undo changes in your Git repositories. Remember to prioritize preserving history and communicating clearly with your collaborators.