Course contents

Revert a published commit

Sign in to run this lab and save your progress

Learn

Everything you've learned in this module so far rewrites history. Reset moves the branch pointer, and the removed commits become unreachable. That's fine for local work no one else has seen.

But what about a commit you pushed to main a week ago that turned out to be a bad idea? A dozen teammates have it in their clones. Reset-and-force-push would erase the commit from the remote and cause chaos when those teammates next pull.

The safe answer is git revert: instead of removing the bad commit from history, add a NEW commit that undoes its effect. Both commits stay in the log. Anyone else's clone stays consistent because nothing was rewritten.

The command

git revert HEAD

Or, revert a specific older commit by SHA:

git revert abc1234

Git computes the inverse diff of the target commit and applies it as a new commit. If the target added a line, the revert commit removes it. If the target deleted a line, the revert commit adds it back. If the target changed a line from A to B, the revert commit changes it from B to A.

By default, Git opens your editor to let you edit the revert commit's message. To skip the editor and use the default:

git revert HEAD --no-edit

The default message is Revert "<original message>", which is usually good enough.

What history looks like after

Before revert:

c3  Bad change     ← HEAD
c2  Good change
c1  Initial

After git revert HEAD --no-edit:

r1  Revert "Bad change"     ← HEAD
c3  Bad change
c2  Good change
c1  Initial

c3 is still there. So is the revert. Together they cancel out: the file contents are as if c3 never happened, but history faithfully records both the mistake and the fix. Anyone reading git log can see exactly what went wrong and when it was undone.

Reset vs revert: which to use

Ask yourself one question: has anyone else seen this commit?

  • If no (local only, unpushed feature branch that only you work on): reset is fine. Simpler, cleaner history.
  • If yes (pushed to a shared branch, someone might have pulled): revert. Always.

That's the whole rule. Reset for private history you can rewrite. Revert for shared history you cannot.

Reverting can conflict too

If subsequent commits depended on the changes made by the commit you're reverting, Git can't cleanly compute the inverse. It pauses with a merge-conflict-style state, and you resolve the same way: edit the file, git add, then finish:

git revert --continue

Or bail out with git revert --abort. Same escape hatches as merge and rebase conflicts.

You can revert a revert

If you revert something and then decide the revert was wrong (the original commit was actually fine), you can revert the revert:

git revert <sha-of-revert-commit>

Now you have three commits: the original, the revert, and the revert-of-the-revert. Everyone can see the whole story. Git logs can get slightly funny to read, but the code is where you want it and no history has been rewritten. Sometimes that's exactly the trade you want to make.

Reverting merge commits

Merge commits (from the diverged module) can be reverted, but the command needs to know which parent line of history to keep:

git revert -m 1 <merge-sha>

The -m 1 means "keep the first parent, undo the second." First parent is usually the branch you merged into (main); second is the branch being merged in (feature). So -m 1 typically means "undo the merge, leave main as it was before the merge landed."

This is one of those commands you rarely need but really want to remember when you do. Any real "roll back a merged feature" scenario ends with git revert -m 1.

Your task

The repository has two commits: Initial (added config.txt with good) and Bad change (changed it to broken). You can't just reset and discard the bad commit — pretend it's already been shared with your team and they have it in their copies. Rewriting history would break their repos. The clean way to undo a shared commit is to add a new commit that reverses its effect. The old commit stays in history; you add an inverse on top. After this, there should be three commits, the latest one starting with Revert, and config.txt should be back to good.