It’s 2 AM, and PagerDuty is sounding alarms relentlessly. Alerts report that the payment gateway is returning massive HTTP 500 errors. The culprit: a pull request merged into the main branch just 5 minutes ago triggered the CI/CD pipeline to auto-deploy to the cluster.
Still groggy, your first instinct is to open the terminal and immediately run git revert <commit_hash>. But Git refuses to execute it:
error: commit 9a4f21b is a merge but no -m option was given.
fatal: revert failed
Production is down, and every minute of downtime costs thousands of dollars. Here is how to resolve the incident in 30 seconds without messing up your team’s git tree.
Emergency Rollback in 3 Steps
If the server is down and you need to restore code to a safe state immediately, follow this process:
Step 1: Get the Hash of the Recently Deployed Merge Commit
Check the last 5 commits on the main branch:
git log --oneline -n 5
The terminal will return a log like this:
9a4f21b (HEAD -> main) Merge pull request #42 from feature/payment-v2
8c1e34a feat: update checkout form
5d2b10f fix: handle payment gateway timeout
1a2b3c4 chore: update dependencies
Step 2: Run the Revert Command with the -m 1 Flag
Specify the mainline branch as the reference point for the rollback:
git revert -m 1 9a4f21b
Git will automatically open an editor to confirm the commit message. Simply keep the default message Revert "Merge pull request #42 from feature/payment-v2" and save.
Step 3: Push Directly to the Remote to Trigger a Rollback Build
git push origin main
The CI/CD pipeline will immediately rebuild the clean codebase from before the merge. System stability is restored. Now, you can take your time to understand Git’s underlying mechanics.
Understanding the -m Flag and Parent Numbers in Git
A regular commit has only 1 parent commit. When executing git revert <hash>, Git simply compares that commit with its parent to reverse the changes.
A merge commit is different. It is the convergence point of at least two branches, meaning it has 2 or more parent commits:
- Parent 1 (Mainline): The receiving branch (usually
mainorproduction). - Parent 2: The branch being merged in (e.g.,
feature/payment-v2).
To inspect the order of these parents, run:
git show 9a4f21b
Observe the second line in the output:
commit 9a4f21b0e419b48...
Merge: 1a2b3c4 8c1e34a
Author: Senior Dev <[email protected]>
Date: Fri Oct 2 02:00:00 2026
What these parameters mean:
1a2b3c4is Parent 1 (HEAD ofmainright before the merge).8c1e34ais Parent 2 (the last commit from thefeature/payment-v2branch).
The -m 1 parameter (short for --mainline 1) specifies the instruction: “Take Parent 1 as the reference baseline and revert all changes introduced by Parent 2.”
The Unexpected Consequence of Reverting a Merge Commit
Many developers mistakenly believe that reverting completely wipes the feature branch from commit history. But that is not how Git works.
The history of past commits remains intact on the Git tree. Git simply creates a new commit that inverts the code at the time of the revert. This creates major trouble when you try to re-merge the feature branch later on.
Re-merging Technique After Fixing the Bug
A very common scenario: The next day, the team identifies the root cause of the Null Pointer error, fixes it, and pushes a new commit to feature/payment-v2. You confidently open a PR targeting main. But when checking the Files Changed tab, you are stunned: All the previous feature code is gone, and the PR only shows the few lines from the new fix commit.
Why does this happen? The main branch still records that the earlier commits were introduced once and subsequently discarded deliberately. Git considers this an intentional removal, so it ignores all the old changes.
3-Step Process to Safely Re-merge:
Step 1: Revert the Previous Revert Commit
We need to restore all original code on main by reversing the previous rollback commit:
# Sync with the latest main branch
git checkout main
git pull origin main
# Get the hash of the revert commit (e.g., a1b2c3d)
git log --oneline -n 3
# Reverse the revert commit (note: this is a regular single commit, so do not use the -m flag)
git revert a1b2c3d
The original feature code is now restored on main.
Step 2: Merge the Bug-Fixed Feature Branch
git merge feature/payment-v2
Git will combine both the restored original code and the latest bugfix commits.
Step 3: Resolve Conflicts (If Any) and Push to Remote
git add .
git commit -m "fix: resolve conflicts and re-merge feature/payment-v2"
git push origin main
Battle-Tested Practices for Handling Git Incidents
After years of running on-call for microservices systems with dozens of daily deploys, here are 4 principles you should follow:
- Avoid
git reset --hardon shared branches: Runninggit reset --hard HEAD~1combined withgit push --forcewill disrupt the local workspaces of other developers on the team. Worse, it destroys the entire audit trail in your CI/CD pipeline. - Specify incident context in the commit message: When reverting, attach the incident ticket to the message for easy tracing later:
git revert -m 1 9a4f21b --no-edit && git commit --amend -m "revert: rollback PR #42 due to checkout timeout (INC-1042)". Note that you should not pass-m "message"directly alongside-m 1, because in a revert command, Git interprets-mas--mainlineby default. - Create an intermediate branch for re-merging: Instead of re-merging directly into
main, create a branch likere-merge/payment-v2and open a Pull Request. Have teammates review the diff before merging to ensure no logic is missing. - Standardize runbooks for your team: Document the
git revert -m 1workflow in your project’s on-call runbook. This allows even freshers or junior engineers on night shift to rollback independently within 2 minutes without waking up the Tech Lead.

