GitHub

How to Revert to a Previous Commit in GitHub

How to Revert to a Previous Commit in GitHub

Reverting to a previous commit in GitHub mostly comes down to git revert or git reset, and the two treat history in opposite ways. git revert adds a new commit that cancels an earlier one. git reset moves the branch back, and the remote only accepts that after a force push.

Whether anyone else has pulled the commit decides it. On a shared branch, revert keeps the history intact and goes up with a plain push.

GitHub Docs state that branch protection rules disable force pushes by default. Put such a rule on the branch and a reset followed by a force push gets rejected with error GH006, unless force pushes have been allowed for whoever is pushing.

So revert is the one that works on a protected branch without touching its settings. If the rule also requires pull requests, the revert commit has to go through one.

Which Method Reverts to a Previous Commit Without Breaking the Branch?

Revert if the commit is already on a shared branch. Reset only if nobody else has pulled it.

History is the deciding factor. A revert adds a commit, a reset removes them.

MethodEffect on historySafe on a shared branchTypical use
git revertAdds an inverse commitYesUndo pushed commits
git resetMoves the branch pointer backNo, needs a force pushDrop local commits
git checkout <hash>None, detached HEADYes, read-onlyInspect an old state
git restore –sourceNone, files onlyYesPull back single files

If the commit has reached GitHub and anyone could have fetched it, revert it. I do that even when a reset would look tidier.

If the commit exists only on your machine, reset is cleaner because the mistake leaves no trace.

The Git manual has a “Reset, restore and revert” section that compares the three commands, and it is worth reading before your first hard reset.

A revert leaves the original commit where it is and records a second one that cancels it, so the log tells the truth about what happened. How git revert works is simple enough. It can reach a commit buried in the middle of the log, not only the latest one.

Why is GitHub the heart of open source?

Uncover GitHub statistics: developer community growth, repository trends, collaboration patterns, and the platform that powers modern software development.

Explore GitHub Data →

Reset rewrites the branch instead. How git reset moves a branch pointer explains why everything after the target commit drops off the branch.

Checkout and restore aren’t reverts at all. Checking out a hash leaves you in a detached HEAD state. Fine for looking around, no good for shipping a fix.

Pros and cons of git revert

History stays intact and a plain push publishes it, no force needed. It works on a commit that isn’t the latest, and if the undo turns out wrong, the revert can itself be reverted.

The cost is one extra commit per revert, and the original mistake stays visible in the log.

Conflicts show up when later commits touch the same lines.

Looking to sharpen your Git skills? Branching, merging, rebasing, and everything else you need - including git rebase, git stash, and commit workflows - is on one page in the Git Cheat Sheet.

Pros and cons of git reset

Reset gives a clean, linear history with no trace of the bad commit.

That tidiness costs something once the branch is on GitHub.

  • The remote rejects the push until you force it
  • Teammates who already pulled keep the old history

A hard reset also throws away uncommitted work. On a branch only you touch, none of this matters much. On main, it does.

How to Find the Commit Hash You Want

Run git log --oneline, spot the commit by its message, and copy the hash at the start of that line. On GitHub, the commit history page of the branch has a copy button beside each commit that gives the full hash.

git log --oneline prints one commit per line, newest first. If you’d rather skip the hash altogether, HEAD~3 points to the fourth last commit (Git documentation).

▶ GIT EXPLAINED

If you commit, branch, or merge code every day, it helps to know how Git came to be. This video covers how Linus Torvalds created Git in just 10 days after a license dispute and explains how its data model actually works.

Linus Torvalds Built Git in Days Out of Spite
Built in 10 Days Out of Spite. Git and its data model explained in plain language.

Short hash or full hash

A commit is named by 40 hexadecimal digits in a SHA-1 repository and 64 in a SHA-256 one, according to the Git hash function transition document.

Git assigns every commit a unique hash when the commit is created, and any unambiguous prefix of it works in a command. By default Git displays at least 7 characters and scales the abbreviation with the repository’s approximate object count, so larger repositories show longer hashes. That behavior was added in 2016 (Git commit e6c587c733).

SHA-256 repositories cannot be read by older Git versions.

Confirm the target before you run anything

Compare the candidate against your current state first. Seeing what git diff reports between the hash and HEAD takes seconds and catches a wrong pick before it costs anything.

A hash copied from the wrong branch is one way this goes wrong. The commit exists in the repository, but not on the branch you are about to change.

git branch --contains <hash> lists the local branches that hold it. Add -a to include remote-tracking branches as well.

How to Revert a Commit with git revert and Push It to GitHub

YouTube player

Run git revert <hash>, save the commit message, then git push. No force is needed because the revert is an ordinary new commit on top of the branch.

  1. Switch to the branch that holds the bad commit and pull the latest changes
  2. Run git status and confirm the working tree is clean
  3. Run git revert <hash> and save the message in the editor
  4. Check the result with git log --oneline, where the revert sits on top
  5. Run git push to publish it to GitHub

What git push does here is send the new commit to the remote branch, and teammates receive it with their next pull. Nobody has to repair their local history.

The same command works outside GitHub, and a separate guide covers how to revert a commit in Git more generally.

Reverting the most recent commit

git revert HEAD undoes the latest commit with no hash lookup. Swap in HEAD~3 to target the fourth last one instead.

Reverting several commits at once

Git accepts a range. The --no-commit flag (short form -n) changes only the working tree and the index, so you make one commit for the whole batch afterward.

The Git manual’s own example is git revert -n master~5..master~2. The range excludes its first endpoint, so that command touches three commits.

When the revert hits a conflict

Conflicts appear when later commits changed the same lines. Edit the conflicted files, stage them with git add, and run git revert --continue to finish.

To back out instead, git revert --abort returns you to the starting state. Git also offers --skip and --quit for a revert that spans several commits.

How to Revert a Merge Commit

Add the mainline flag, as in git revert -m 1 <merge-hash>. Without it Git refuses, because it cannot tell which side of the merge to keep.

Parent number 1 is the branch you were on when the merge happened, normally main.

A merge commit is what git merge produces when it joins two lines of history, so it has two parents. Run git show on it and read the “Merge:” line to see them in order.

Squash-merged pull requests are the easy case. They land as one ordinary commit, so a plain revert works with no -m.

What a merge revert does to a later re-merge

Reverting a merge declares that you will never want the tree changes the merge brought in, per the Git documentation.

Merging the same branch again therefore skips everything from before the revert. The revert-a-faulty-merge How-To in the Git docs splits the fix into two cases.

  • If corrections were added on top, revert the revert with git revert <revert-hash>, then merge again
  • If the branch was rebuilt from scratch, leave the revert alone and merge the new branch as it is

The same How-To warns against reverting a revert blindly. Pick the case first.

How to Reset a Branch to a Previous Commit

Run git reset --hard <hash> to move the branch back and make every file match that commit. Use --soft or --mixed when the later changes should stay on disk.

ModeBranch pointerIndexWorking directory
–softMovesUntouchedUntouched
–mixed (default)MovesResetUntouched
–hardMovesResetReset

The mode defaults to --mixed when you omit it (Git documentation).

git reset –soft

With --soft the branch moves back, and the undone changes sit in the staging area, ready to commit again.

git reset --soft HEAD~3 followed by one new commit merges three commits into one.

git reset –mixed

Mixed is what a bare git reset <hash> gives you. Changes stay in your files but are no longer staged.

Pick it when you want to rework the commits rather than keep them as they were.

git reset –hard

Hard discards every uncommitted change in tracked files. For work that was never committed, there is no getting it back, though the old tip stays reachable through ORIG_HEAD for the moment.

Run git status first. If there is work you want back, saving it with git stash takes one command.

Git copies the old head to .git/ORIG_HEAD on a reset, so git reset --hard ORIG_HEAD undoes a mistake right after it happens (Git documentation).

Target a specific commit by hash, or use HEAD~1 for the one before the tip. Either way the reset moves your local branch only, and GitHub keeps the later commits until you push the rewritten history.

Force Pushing a Reset to GitHub and Protected Branches

Use git push --force-with-lease origin <branch> to publish a reset. It overwrites the remote branch only if nobody has pushed to it since your last fetch.

A plain push fails after a reset because the remote branch holds commits your local branch no longer contains. The git push documentation describes this as updating a remote ref that is not an ancestor of the local one.

FlagOverwrites whenMain risk
–forceAlwaysErases a teammate’s newer push silently
–force-with-leaseRemote matches your tracking branchTrusts your last fetch
–force-with-lease=<branch>:<hash>Remote tip equals the hash you nameYou must type the expected hash

To force a single branch, put a + in front of the refspec, as in git push origin +feature-x. Every other branch stays on the normal rules.

What a protected branch does to a force push

GitHub’s branch protection rules disable force pushes by default, according to GitHub Docs. A blocked push comes back with remote: error: GH006: Protected branch update failed for refs/heads/main.

A force push replaces the branch tip in the remote repository, so protection exists precisely to stop it on branches everyone builds from.

Repository admins can tick “Allow force pushes” inside the rule, which then offers Everyone or a named list of actors. Rulesets are GitHub’s alternative to branch protection rules.

Skip all of that for main. Revert the commit instead, and keep force pushes for feature branches only you use.

Can You Revert a Commit from the GitHub Website or GitHub Desktop?

Yes. The website reverts a merged pull request, and GitHub Desktop reverts a single commit. Neither one resets a branch or rewrites history.

Reverting a merged pull request on GitHub

As of October 2026, the Revert button opens a new pull request that reverses the original merge commit, per GitHub Docs. You need write permission on the repository.

  1. Open the Pull requests tab and pick the merged one
  2. Click Revert near the bottom of the page
  3. Merge the pull request GitHub creates

The docs tell you to revert individual commits instead when the revert causes merge conflicts, or when the original pull request was not merged on GitHub.

If the button is missing, ask a repository administrator for write access.

Reverting a commit in GitHub Desktop

One commit at a time, that is the model.

In GitHub Desktop, the graphical client, you open the History tab and right-click the commit. Revert Changes in Commit is in the menu. The revert is itself a commit, and the original stays in the history (GitHub Docs).

Reverting several commits works best from newest to oldest. A different order can produce merge conflicts.

Push the new commit afterward so it reaches GitHub.

How to Recover Commits After a Hard Reset

Run git reflog, find the entry from just before the reset, and restore it with git reset --hard <hash>. The commits are not gone, only unreferenced.

ORIG\_HEAD remembers only the last drastic move of HEAD. The reflog covers the older mistakes it has already forgotten.

git reflog lists every HEAD move, with the reset as the newest entry and the lost tip right below it. To save that commit without touching your working directory, run git branch rescue <hash>.

Then git reset --hard <hash> moves the branch back, and discards whatever is uncommitted at that moment.

HEAD@{1} points at the pre-reset state only when nothing else has moved HEAD since. Read the entries before trusting an index.

How long the reflog keeps commits

Reflog entries that are still reachable live 90 days by default (gc.reflogExpire). Entries no longer reachable from the branch tip get 30 days (gc.reflogExpireUnreachable). After that, git gc waits a 2 weeks grace period before it prunes unreferenced objects (gc.pruneExpire).

The Git config reference defines the 30-day window as entries not reachable from the current tip. A commit dropped by a hard reset fits that definition, so the shorter window applies to it.

Many tutorials quote a flat 90 days. The Git documentation splits it in two, and the split decides how long you have.

What the reflog cannot bring back

Committed work dropped by a reset comes back, and so does the tip of a deleted branch. Commits replaced by an amend or rebase can be recovered too.

Uncommitted edits wiped by --hard are gone for good. So are files removed by git clean, and so are commits whose entry expired and whose objects git gc already pruned.

The reflog lives in your local .git directory, so it cannot recover a commit that only ever existed in someone else’s clone. For a dangling commit with no reflog entry, git fsck --lost-found lists candidates to inspect.

When Reverting to a Previous Commit Fails

Most failed reverts trace back to conflicts, a detached HEAD, a secret that stays in history, or teammates who keep the old branch.

FailureCauseFix
Revert stops with conflictsLater commits edited the same linesResolve files, continue the revert
New commits belong to no branchWork done after checking out a hashCreate a branch before switching away
Secret still visibleThe original commit remains in historyRotate the credential
Clone out of syncForce push rewrote the remote branchRealign each clone

Conflicts and reverts that apply cleanly

Git cannot apply the inverse patch when later commits touched the same lines. Resolving merge conflicts in Git works the same way here as it does for a merge, then you run git revert --continue.

A conflict-free revert is not automatically a working one. Run the tests before you push, because code written later may depend on the change you removed.

Work stranded in a detached HEAD

Checking out a hash leaves you in a detached HEAD state, and commits made there belong to no branch.

Once you switch away, only the reflog still points at them. Run git switch -c rescue before leaving.

A revert does not remove a leaked secret

The original commit stays in the repository history after a revert, as the GitHub Desktop docs spell out. Anyone with the repository can still read it.

A reset and force push pulls the commit off the branch, but copies already cloned or forked still hold it. Treat the credential as exposed and rotate it.

Teammates holding the old history

After a force push, every clone that fetched the old branch still carries it.

Their next pull then conflicts with history that no longer exists on GitHub.

Reverting to a Previous Commit in GitHub FAQ

How do I bring back one file from an older commit without reverting the rest?

Run git restore --source=<hash> <file>. It overwrites that file in your working tree with the old version and leaves history alone.

Commit the file afterward to record the change.

Does git revert delete the original commit?

No. The original commit stays in the history, and the revert is recorded as a second commit on top of it.

Only a reset drops commits from the branch.

How do I save uncommitted work before a hard reset?

Run git stash first, reset, then git stash pop to bring the changes back. Add -u to the stash command when untracked files are involved.

Skipping this step costs you the edits, because the reflog never recorded them.

Can I look at an old commit on its own branch instead of resetting?

Yes. git switch -c <new-branch> <hash> creates a branch that starts at that commit.

Your current branch stays untouched, which makes it a safe way to test an old state.

Can I run these commands from Visual Studio Code?

Yes. The integrated terminal runs the same Git commands as any other terminal, and ` Ctrl+ “ opens it.

Git behaves exactly as it does outside the editor.

Keeping Teammates in Sync After a Revert

Reverting to a previous commit in GitHub with git revert needs no cleanup from teammates, because a normal pull delivers it. A reset plus force push does need one, since every clone still holds the dropped commits.

Announce the force push before running it. Each clone then gets realigned with git fetch followed by git reset --hard origin/<branch>, and open pull requests should be checked for the dropped commits.

Announcing comes first because a pull made beforehand merges the dropped commits back into the branch, and untangling that means resolving merge conflicts on a branch that has already moved on.

Anyone with unpushed commits parks them on a branch first, since the hard reset removes them from the working branch.

Reset buys a tidy log and costs each teammate a realignment. As of October 2026, GitHub Docs list a “Block force pushes” rule in rulesets that is on by default, and bypass lists decide who may push past it. That changes who can reset, not what teammates have to do afterward.

Bogdan Sandu

Stay sharp. Ship better code.

Every week: one curated article, one tool worth knowing, one tip you can use tomorrow. No noise, no padding.