Reverting multiple commits in Git is one of those tasks that looks simple until you do it on a shared branch with a release deadline. The difference between git revert two commits and rewriting history can decide whether your team keeps moving or spends an hour untangling a broken branch.
CompTIA Pentest+ Course (PTO-003) | Online Penetration Testing Certification Training
Discover essential penetration testing skills to think like an attacker, conduct professional assessments, and produce trusted security reports.
Get this course on Udemy at the lowest price →Quick Answer
git revert two commits is the safest way to undo committed changes on a shared branch because it creates new commits that reverse the old ones without rewriting history. Use git revert for public branches, git reset only for private local work, and test the result before pushing. For merge commits and mixed histories, inspect the commit graph first.
Quick Procedure
- Inspect history with
git log --oneline --graph. - Identify the commits you want to remove.
- Run
git revert <commit-hash>for each commit or use a range. - Resolve any conflicts, then continue the revert.
- Review the result with
git diffandgit log. - Test the branch before pushing.
- Use
--no-commitif you want one combined revert commit.
| Primary Topic | How to revert multiple commits in Git |
|---|---|
| Best Safe Method | git revert for shared branches as of May 2026 |
| Riskier Method | git reset --hard for private work only as of May 2026 |
| Useful Commands | git log, git show, git revert --no-commit as of May 2026 |
| Merge Commit Handling | git revert -m as of May 2026 |
| Typical Use Case | Undoing bad commits after push without rewriting shared history as of May 2026 |
For teams practicing source code control with Git, this is a practical skill, not an academic one. It matters in release branches, hotfixes, security rollbacks, and any situation where you need to reverse a bad change without disrupting everyone else’s work.
It also connects well to the kind of disciplined change control covered in the CompTIA Pentest+ Course (PTO-003) | Online Penetration Testing Certification Training, because real assessments often produce code, config, or documentation changes that need to be rolled back cleanly and documented clearly.
Understanding Git Commit History
Git is a distributed version control system that stores work as snapshots linked in a commit graph, not as a simple line-by-line undo stack. That structure is why reverting two commits is not always as straightforward as pressing an undo button.
Each commit points to a parent commit, and that parent relationship is what makes history a chain. When you revert multiple commits, the order matters because later commits may depend on earlier ones. If you remove changes in the wrong sequence, you can create conflicts or break code that only makes sense in the context of later edits.
Start by reading history before changing it. The most useful commands are the ones that show structure and content together:
git logfor full commit history.git log --onelinefor a compact view.git log --oneline --graph --decoratefor branch structure.git show <commit-hash>for the exact patch in one commit.
When you need to revert multiple commits, identify whether the bad changes are consecutive or scattered. Consecutive commits are easier to undo with a range. Scattered commits usually require individual reverts or a temporary branch so you can isolate the change set before pushing anything back upstream.
A clean revert starts with a clean reading of history. If you do not know exactly which commit changed what, you are guessing, not reverting.
How to spot the right commits quickly
Use git log --oneline --graph to find the point where the problem started. Then inspect each candidate with git show and look for the commit that introduced the defect, the regression, or the unwanted configuration change. If a branch contains merge commits, grouped changes, or backported patches, take extra time to trace the actual change rather than relying on the commit message alone.
In practice, the safest workflow is to mark a known-good commit, identify the first bad commit after it, and determine whether you need to revert one commit, git revert two commits, or remove an entire range. That decision should be based on the graph, not memory.
Revert Vs Reset: Choosing The Right Undo Method
git revert is the command that creates a new commit reversing the changes introduced by an earlier commit. git reset is the command that moves the branch pointer, which can rewrite history and make shared branches harder to manage.
That difference is the core decision. If the commits are already pushed to a shared repository, revert is usually the correct choice because it preserves auditability. If the commits exist only on your local feature branch and no one else has pulled them, reset may be acceptable because you are not disrupting anyone else’s history.
Here is the practical comparison:
| git revert | Safe for shared branches, preserves history, creates a new undo commit, and is easier to coordinate in teams. |
|---|---|
| git reset | Fast for private work, but risky on public branches because it rewrites commit history and can break collaboration. |
Team workflow matters here. If your branch is mirrored to a remote repository and teammates may already have cloned it, history rewriting becomes a coordination problem. Revert avoids that problem by adding a new commit that says, in effect, “this change was rolled back.”
Warning
Do not use git reset --hard on a shared branch unless your team has explicitly agreed to rewrite history. On public branches, revert is the safer default.
That auditability is why many release managers prefer revert for production branches. It leaves a visible trail for code review, incident review, and change-management documentation.
For current Git behavior and reference commands, consult the official documentation at Git Documentation. For secure branching practices and code review discipline, the ideas align closely with change-control guidance found in NIST material on controlled system changes.
Reverting A Single Commit Before Handling Multiple Commits
The basic syntax is git revert <commit-hash>. That command applies the inverse of the selected commit and opens your editor for the revert message unless you use a flag to skip it.
After the revert commit is created, your branch history does not lose the original commit. Instead, the new revert commit sits on top and cancels out the earlier change. That is exactly why revert is safer than reset on shared branches.
- Find the commit hash. Use
git log --onelineorgit showto identify the exact commit you want to undo. - Run the revert. Use
git revert abc1234, replacing the hash with the real one. - Resolve conflicts if needed. If the patch overlaps with later changes, Git pauses and asks you to fix the files manually.
- Finish the revert. Use
git addon resolved files and thengit revert --continue. - Verify the outcome. Check the new history and compare the branch state with
git diff.
Common issues include content conflicts, file deletions, and patch failures when the file has drifted too far from the original version. When that happens, open the files Git marks as conflicted, inspect the conflict markers, and make a deliberate edit rather than guessing.
Once you understand single-commit revert behavior, reverting two commits becomes a matter of repeating the same operation or selecting both commits as a batch. That is the cleanest way to build confidence before moving on to git revert two commits in a more complex branch.
How Do You Revert Multiple Commits With A Range?
You can revert multiple commits with a range by selecting a sequence of commit hashes and letting Git apply the inverse changes in order. The key is to understand the inclusive and exclusive parts of the selection so you do not miss the commit that actually introduced the problem.
In many cases, you will use a commit range that starts after a known-good commit and ends at the latest bad commit. Git then processes those commits one at a time unless you batch them with --no-commit.
A common mistake is assuming the range syntax includes both endpoints in every case. It does not always behave that way the way humans expect, so always confirm the selected commits with git log --oneline before executing the revert.
What range selection looks like in practice
Suppose the problem began after commit abc1234 and the latest bad change is def5678. You might inspect the commits between them, then decide whether to revert them individually or as a set. If you are working with git revert two commits, verifying that the pair is actually consecutive saves time and prevents accidental rollback of unrelated work.
When ranges include merges or commits from another topic branch, the results can be messy. If the branch has unrelated changes mixed into the same span, create a throwaway branch and test the revert there first. That gives you a safe place to observe conflicts before touching the shared branch.
For range-based decisions, the official behavior is documented in the Git reference manual at git revert. If your team uses formal change controls, documenting the selected range is just as important as running the command itself.
Reverting Several Commits In One Commit
--no-commit lets you apply multiple reverts without creating one revert commit per original commit. That is useful when you want one clean rollback commit instead of a long trail of small undo commits.
This workflow is better when the changes are tightly related, when code review needs to see one logical rollback, or when you want to inspect the combined effect before finalizing anything. It also makes git revert two commits feel less like a sequence of unrelated operations and more like one controlled change.
- Identify the commits. Confirm that the commits are part of the same problem set and are safe to revert together.
- Apply the reverts without committing. Use
git revert --no-commit <hash1> <hash2>or another selected set. - Inspect the staged result. Use
git diff --cachedto review the combined patch. - Adjust anything unexpected. If one revert removes too much or too little, edit the files before committing.
- Create the final commit. Use a descriptive message that explains why the rollback happened.
This approach works especially well when a bad change spans several files but has one root cause. You can verify the exact combined rollback before recording it in history. That means fewer commits, cleaner review, and less noise in future audits.
If you need to compare the staged rollback against the original branch, use git diff --cached and git diff HEAD~1 carefully, then run your test suite. A clean staged diff is not enough if the runtime behavior still fails.
Note
When you need one reviewable rollback, use --no-commit. When you need a precise audit trail for each removed change, commit each revert separately.
Handling Merge Commits And Complex Histories
Merge commits are commits with more than one parent, and they need special handling because Git must know which parent line to preserve. That is why reverting a merge commit often requires the -m option.
The -m flag tells Git which parent is the mainline. In practical terms, you usually choose the parent that represents the branch you want to keep as the base. If you choose the wrong parent number, the revert can remove the wrong side of the merge or produce confusing history.
Use git show <merge-hash> to inspect the merge and understand how the parents line up. Then test the revert on a local branch before applying it to shared work.
Why merge reverts are tricky
Merge reverts can come back to haunt you during later merges. If you revert a merge commit and then merge the same topic branch again later without carefully managing the history, Git may try to reintroduce code you already intended to keep out. That is one reason developers often isolate the affected changes on a temporary branch first.
For complex histories, the safer strategy is to break the problem apart. Identify the exact commits, separate the good and bad changes if possible, and simplify the graph before you revert anything on a branch other people depend on. In large repositories, clarity beats speed every time.
The Git documentation on merge behavior is the right official reference here, and the same principle applies in secure configuration management: understand the dependency chain before changing the history. That discipline also maps well to the reporting mindset taught in a penetration-testing workflow, where transparency matters as much as the technical fix.
Managing Conflicts During A Revert
Conflicts happen because the changes you are trying to remove overlap with later edits. Git cannot safely decide which lines to keep, so it stops and asks you to resolve the situation manually.
The resolution workflow is straightforward, but it has to be done in order. Start with git status to see which files are conflicted, open the files to inspect the conflict markers, and then edit the content until the result reflects the intended rollback.
- Check the status. Run
git statusto identify the files Git wants you to fix. - Open the conflicts. Review the conflict markers and determine which side reflects the desired post-revert state.
- Edit carefully. Remove the conflict markers and keep the correct code or configuration.
- Stage the resolution. Use
git add <file>for each fixed file. - Continue the revert. Run
git revert --continueto complete the commit. - Run tests. Validate the behavior before you push anything.
If the conflict path gets messy, use git revert --abort and start over. That is better than forcing a half-fixed rollback into history. A good diff tool or merge tool can also show you exactly what the revert is trying to remove, which reduces guesswork and helps you avoid accidentally deleting a later fix.
A revert conflict is a signal, not a failure. It means the branch moved on, and your rollback must account for the newer work that followed.
Running tests after conflict resolution is not optional. A revert that compiles but breaks authentication, logging, or deployment steps is still a bad revert.
For broader engineering context, this is where OWASP guidance on careful change validation and NIST Cybersecurity Framework principles around controlled change both point in the same direction: verify the fix, do not assume it is correct.
Alternative Strategies For Undoing Multiple Changes
Not every rollback should use revert. Sometimes a different tool is safer, faster, or easier to explain to the team.
git reset --hard is appropriate when the commits are local and have not been shared. It wipes the branch pointer back to an earlier commit and discards later work from the working tree. That is efficient, but it is also destructive if used on a branch others depend on.
git cherry-pick is useful when you want to keep selected good commits and leave out the bad ones. This is common in release branches where one or two fixes must move forward, but a broader feature set must stay out.
Interactive rebase lets you reorder, drop, or squash local commits before they are pushed. It is excellent for cleaning up personal history, but it should be used carefully if the branch is already public.
| reset | Best for local, unshared work when history can be rewritten safely. |
|---|---|
| cherry-pick | Best for selecting good commits while excluding bad ones from a branch. |
| rebase | Best for reorganizing private history before collaboration begins. |
Safety, transparency, and coordination should drive the decision. If history must be preserved, revert is usually the right answer. If history can be rewritten and no one else is affected, reset or rebase may be the better fit.
For branch management and remote coordination, official Git guidance remains the best reference at Git Documentation. If your organization uses formal change tickets, match the technical approach to the approval trail, not the other way around.
Best Practices For Managing Changes After Reverting
Large rollbacks are easier to manage when the branch was built with good habits from the start. A backup branch gives you a safety net before you attempt a large revert or any other history-sensitive action.
Small, atomic commits also help. If one commit changes authentication, another changes logging, and a third changes UI text, you can revert the problematic one without disturbing unrelated work. If everything is bundled into one giant commit, even git revert two commits can turn into a debugging session.
Commit messages matter too. A good revert message should explain why the change was backed out, not just what was removed. That helps future reviewers understand whether the rollback was due to a bug, a security issue, a failed build, or a temporary operational decision.
- Create a backup branch before a broad revert.
- Keep commits small so future reversions are precise.
- Write descriptive messages that explain the reason for the revert.
- Run tests, linters, and builds after the rollback.
- Notify teammates if a shared branch or release branch changed.
Communication is part of the technical fix. If the branch feeds staging, production, or a release candidate, tell the team what changed, why it changed, and whether any follow-up work is needed. Good Git hygiene is not just command discipline; it is team discipline.
For change-management context, the same practices show up in ITIL processes and in operational guidance from CISA around controlled response and recovery. The common thread is simple: document the change and verify the result.
When To Reapply Or Reintroduce Reverted Changes
Some reverts are temporary. A feature may be rolled back to stabilize a release and then reintroduced later after the bug is fixed or the dependency issue is resolved.
The safest way to reapply a change is to create a new commit or cherry-pick the corrected work, not to blindly reverse the reverse. Reverting the revert can work in some cases, but it becomes confusing when the branch has moved forward and other commits now depend on the intervening state.
- Confirm the original reason for the revert. Make sure the underlying issue is actually fixed.
- Check branch history. Review whether later commits depend on the reverted behavior.
- Reintroduce with a clean commit. Prefer a fresh commit or
git cherry-pickover a fragile history trick. - Document the return. Explain why the change is coming back and what changed since the rollback.
- Test again. Verify that the reintroduced code behaves correctly in the current branch state.
Feature flags can reduce the need for repeated revert cycles because they let you disable behavior without deleting the code. Branch-based workflows help too, especially when you need a temporary rollback in one environment but not in another. If you must bring the change back, make that decision visible in history so nobody has to guess why the code returned.
The risk here is accidental “revert the revert” confusion. That can happen when someone sees a rollback commit and assumes the opposite action is always correct. It is not. Reintroducing changes should be intentional, reviewed, and documented.
Key Takeaway
Revert the original problem only after confirming the branch state, the business reason, and the dependency chain. Reapply changes with a fresh commit when possible, and avoid guessing with “revert the revert.”
How To Verify It Worked
The revert worked if the commit history is intact, the unwanted changes are gone, and the branch still builds and tests cleanly. Do not stop at “Git accepted the command.”
Start with git log --oneline and confirm that the revert commit is present. Then inspect the branch with git diff or git diff HEAD~1 to make sure the removed changes match your intent. If you reverted two commits, the final code should reflect the combined reverse of both changes, not a partial rollback.
- History check: The revert commit appears in
git log. - Diff check: The unwanted changes are no longer present in
git diff. - Build check: The project still compiles or packages successfully.
- Test check: Automated tests pass, or the expected failing case is gone.
- Conflict check: No unresolved merge markers remain in the files.
Common failure symptoms include a revert that compiles but breaks behavior, a revert that leaves part of the original change behind, or a conflict resolution that accidentally removed a later fix. If you see those signs, stop and inspect the patch again before pushing.
For broader operational validation, compare the outcome with your test suite, linting rules, and deployment checks. If this change affects a release branch, review it like any other production change: verify, document, then push.
Official references for command behavior remain the best source of truth: Git revert documentation and the broader Git docs at git-scm.com.
How Do You Revert Multiple Commits Safely In Real Teams?
You revert multiple commits safely by matching the method to the branch state. On a shared branch, git revert is the default because it preserves history. On a private branch, reset or rebase may be acceptable if no one else has pulled the work.
That means git revert two commits is not just a command pattern. It is a workflow decision about whether you need a reversible audit trail or a clean rewrite. The right answer depends on collaboration, release timing, and whether the branch is already public.
In team environments, the safest Git strategy is the one that keeps history understandable for the next person who opens the branch.
If the history is straightforward, revert the specific commits. If the history is tangled, isolate the problem on a temporary branch, inspect the graph, and then choose between revert, cherry-pick, or a controlled reset. The goal is not to use the shortest command. The goal is to make the least dangerous change.
That is the same discipline good security teams use when they patch, roll back, and document a system under change control. Clear history, clear accountability, and clear verification make the whole process manageable.
Key Takeaway
Use git revert for shared branches, use git reset only for private work, and confirm the commit graph before reversing more than one change.
When the history is complex, batch with --no-commit, inspect the combined diff, and test before pushing.
Merge commits need special care with -m, and future merges can reintroduce reverted code if you do not manage the branch carefully.
CompTIA Pentest+ Course (PTO-003) | Online Penetration Testing Certification Training
Discover essential penetration testing skills to think like an attacker, conduct professional assessments, and produce trusted security reports.
Get this course on Udemy at the lowest price →Conclusion
Reverting multiple commits in Git is manageable when you choose the right method for the branch in front of you. If the work is shared, git revert is the safest path because it preserves history and leaves a clear audit trail. If the work is local and unpushed, git reset or rebase may be appropriate, but only when rewriting history will not affect anyone else.
For consecutive bad commits, you can revert them individually or use a range. For cleaner history, use --no-commit and create one consolidated revert. For merge commits and tangled histories, inspect the graph first and treat conflicts as part of the process, not an exception.
Test the result, communicate the change, and verify that nothing else broke. Good Git hygiene turns a potentially messy rollback into a predictable routine, and that is what keeps collaborative development moving.
If you are building stronger command-line and change-management habits, the same discipline also supports the practical skills emphasized in the CompTIA Pentest+ Course (PTO-003) | Online Penetration Testing Certification Training.
Git is a trademark of Software Freedom Conservancy. CompTIA® and Security+™ are trademarks of CompTIA, Inc.