Git Revert to Previous Commit: Reset, Revert, or Checkout

Tested on RHEL 10.2 (Coughlan)
Package git 2.52.0
Applies to Any host with Git installed
Privilege Normal user
Scope Go back to an earlier commit or undo its effect — git revert on shared branches, git reset locally, detached inspection, single-file restore, merge revert, and reflog recovery pointers. Not a full reset, revert, or reflog tutorial.
Related guides Git revert examples
Git reset examples
Git reflog tutorial
Git discard changes
Git remove commit

Going back to a previous commit can mean four different things:

  • undo a bad commit while keeping history;
  • move your local branch back;
  • temporarily inspect an older version;
  • restore only one file from an older commit.

Git uses a different command for each goal — git revert, git reset, detached git switch, or git restore --source.

HEAD is the commit your current branch points to. HEAD~1 is one commit before it, and HEAD~2 is two commits before it. When you know which of the four goals you have, the decision table below sends you to the right section.


Choose the Right Way to Go Back

Your goal Safe on shared branches? Command
Undo a commit that others may have pulled Yes git revert <commit> or git revert HEAD
Move your local branch back N commits Local only git reset --hard HEAD~N — see Git reset examples
Undo last commit but keep edits staged Local only git reset --soft HEAD~1
Inspect an old snapshot without moving the branch Yes (read-only) git switch --detach <commit>
Restore one file from an older commit Yes git restore --source=<commit> -- file
Undo a merge commit on main Usually yes git revert -m 1 <merge-commit>
Recover a commit removed by reset Local recovery git reflog then git reset --hard <hash>

If the problem is uncommitted edits in your working tree — not an old commit — see Git discard changes. For every git revert flag and range syntax, see Git revert examples.


Revert vs Reset in Plain Terms

Both commands can make your project look like an earlier commit, but they treat history differently:

  • git revert adds a new commit that reverses an older one. The bad commit stays in the log; a follow-up commit cancels its changes. Use this when the branch is shared or already pushed.
  • git reset makes an older commit become the latest commit on your local branch. Commits after that point drop off your branch (until reflog recovery). Use this mainly for local work you have not shared. In Git terms, it moves the branch pointer backward.

Example history before any fix:

text
A → B → C (HEAD, main)

After git revert C on a shared branch:

text
A → B → C → D (HEAD)

Commit C remains; D undoes its file changes.

After git reset --hard B locally:

text
A → B (HEAD)

Commit C is no longer on the branch — recoverable via reflog for a while.


Undo a Commit That Was Already Pushed

Scenario: the latest commit on main introduced a bad change and teammates may have pulled it. Revert adds a safe undo commit instead of rewriting history.

Start from a branch with three commits; the latest is the one you want to cancel:

bash
git log --oneline -3

Sample output:

output
aa5020a Third commit - bad change
9dcc7e5 Second commit
c46b413 Initial commit

Revert the tip commit. Git opens an editor for the revert message unless you pass --no-edit:

bash
git revert HEAD --no-edit

Git creates a new commit that reverses the changes from HEAD:

output
[main 10e0380] Revert "Third commit - bad change"
 1 file changed, 1 insertion(+), 1 deletion(-)

The log now shows both the original commit and the revert on top:

bash
git log --oneline -4
output
10e0380 Revert "Third commit - bad change"
aa5020a Third commit - bad change
9dcc7e5 Second commit
c46b413 Initial commit

The working tree matches the state before the bad commit — here app.txt again holds v2 from the second commit — but history stays intact for anyone who already pulled aa5020a.

To revert an older commit (not HEAD), name its hash from the log above — here, undo Second commit:

bash
git revert 9dcc7e5 --no-edit

That removes only the changes from that commit and leaves later commits in place. For range reverts, conflict handling, and --no-commit, see Git revert examples.


Move Your Branch Back Locally

Scenario: you have not pushed the last commit (or the branch is yours alone) and you want an earlier commit to become the latest commit on this branch.

Drop the last commit but keep changes staged

When to use this: you committed too early and will edit the message or files before committing again.

bash
git reset --soft HEAD~1

The commit disappears from the branch, but Git keeps its changes staged:

bash
git status -sb
output
## main
A  b.txt

git log --oneline now shows the previous commit as the branch tip; the removed commit’s changes remain staged in b.txt.

Drop the last commit and discard its changes

When to use this: the commit and its edits should both go away on a local branch.

--hard does not only remove the last commit’s changes. Any other staged or unstaged changes in tracked files can also be overwritten, so check git status first:

bash
git status -sb

When the tree is clean (or you accept losing uncommitted tracked edits), reset back one commit:

bash
git reset --hard HEAD~1

Git moves HEAD back one commit and resets tracked files to match:

output
HEAD is now at 0dfe067 v2

Confirm the branch tip no longer lists the removed commit:

bash
git log --oneline
output
0dfe067 v2
de2bad3 v1

The former tip commit (v3) is off the branch. --hard deletes those file changes from disk — not recoverable with git restore, though reflog may still list the old tip for a time.

For --mixed, path-only reset, matching origin/main after fetch, and reset-versus-revert detail, see Git reset examples.


Inspect an Old Commit Without Changing the Branch

Scenario: you want to read code or run tests at an older snapshot without moving main.

Check out that commit in detached HEAD mode:

bash
git switch --detach HEAD~1

Git prints where you landed:

output
HEAD is now at de2bad3 v1

git status -sb confirms you are not on a branch:

bash
git status -sb
output
## HEAD (no branch)

Commits you make here are not on main until you attach them to a branch. If you decide to keep work created while detached, create a branch before switching away:

bash
git switch -c test-old-version

The new branch starts at the commit you are currently viewing. Any commits you make from that point will then belong to test-old-version. To return to normal development on main without keeping detached work:

bash
git switch main

Older Git versions use git checkout <commit> for the same detached state; git switch --detach is the modern spelling.


Restore One File From an Older Commit

Scenario: only one file should match an older commit; the rest of the branch stays as-is.

With uncommitted edits in app.txt, replace your current file with the version stored one commit earlier:

bash
git restore --source=HEAD~1 app.txt

The file on disk now matches that older commit; other files and commits are unchanged:

bash
cat app.txt
output
v2

Because the branch tip still has the newer content, status should show the file as modified:

bash
git status -sb
output
## main
 M app.txt

Git shows app.txt as modified because your branch tip still has the newer content — you have a local edit ready to commit or discard. git restore --source changes the file in your working tree; it does not move the branch or remove any commits. To copy from a specific hash, replace HEAD~1 with that commit id.


Revert a Merge Commit

Scenario: a merge to main should be undone without rewriting history.

After a non-fast-forward merge, find the merge commit hash:

bash
git log --oneline --graph -5
output
*   a39da0e Merge branch 'feature'
|\  
| * f22cbb0 feature work
* | d96cddb main moves forward
|/  
* 543e74a main init

Revert the merge, keeping the first parent (usually main before the merge):

bash
git revert -m 1 a39da0e --no-edit
output
[main f8e252c] Revert "Merge branch 'feature'"
 1 file changed, 1 deletion(-)
 delete mode 100644 feat.txt

After the revert, feat.txt from the feature branch is gone but the merge commit remains:

bash
git log --oneline --graph -5
output
* f8e252c Revert "Merge branch 'feature'"
*   a39da0e Merge branch 'feature'
|\  
| * f22cbb0 feature work
* | d96cddb main moves forward
|/  
* 543e74a main init

In a typical feature → main merge, -m 1 means keep the main side and undo the changes that the merge brought in from feature. Git calls that first parent the mainline. Unusual parent choices and merge-revert side effects — including how later merges treat reverted changes — are covered in Git revert examples.


Recover a Commit After Reset

Scenario: you ran git reset --hard and need the old tip back.

Reflog records where HEAD has been, including commits no longer on the branch:

bash
git reflog -5
output
0dfe067 HEAD@{0}: reset: moving to HEAD~1
8c861a7 HEAD@{1}: commit: v3
0dfe067 HEAD@{2}: commit: v2
de2bad3 HEAD@{3}: commit: v1

You are now at 0dfe067 — the same tip shown after git reset --hard HEAD~1 above. In this example, 8c861a7 is the commit recorded just before the reset and is the old branch tip you want to recover. If that hash is the one you need, move your current branch there:

bash
git reset --hard 8c861a7

Reflog entries expire eventually; on shared branches, prefer git revert so teammates are not surprised by a force push. Full walkthrough: Git reflog tutorial.


Troubleshooting

Symptom Likely cause Fix
error: commit … is a merge but no -m option given Reverting a merge without naming a parent Run git revert -m 1 <merge-commit> (usually parent 1 is main)
Revert stops with conflict markers The reverse patch does not apply cleanly Resolve files, git add them, then git revert --continue
git reset --hard removed work you still need Reset moved the branch and cleared files Find the old tip in git reflog, then git reset --hard <hash>
Detached HEAD warning after old commit You checked out a commit, not a branch git switch main (or your branch name) before new commits
Teammates reject your push after reset Reset rewrote history they already pulled Use git revert instead, or coordinate a force push only when the branch is truly yours
Only one file should roll back Whole-commit revert is too broad git restore --source=<commit> -- path

References


Summary

Going back to a previous commit starts with what you need: cancel a change on a shared branch, move a local branch back, inspect history, or fix one file. The decision table maps each goal to git revert, git reset, detached git switch, or git restore --source.

On branches others pull from, git revert is the default safe path — it adds an undo commit and leaves the original in the log. Local-only mistakes on commits you have not shared are where git reset is appropriate; choose --soft, --mixed, or --hard depending on whether you want to keep the changes. If you reset too far, check git reflog before you panic.

Detached checkout lets you read or test an old tree without moving main. Create a branch with git switch -c if you want to keep commits made while detached. Single-file rollback uses git restore --source so the rest of the branch stays put. Merge undos on a typical feature → main flow use git revert -m 1 to keep the main side.

When you outgrow this overview, the linked guides cover revert ranges, every reset mode, and full reflog recovery — but the split to remember is revert for shared history, reset when you want a local branch to go back to an earlier commit, and restore when only one path should change.


Frequently Asked Questions

1. How do I revert to a previous commit in Git?

On a shared branch, run git revert with the commit hash or HEAD to add a new commit that undoes that change. On a local-only branch, git reset --hard HEAD~1 moves the branch back one commit, so the latest commit is no longer part of the branch history.

2. How do I go back to a previous commit without losing history?

Use git revert commit-hash. Git keeps the original commit and adds a new one that reverses its changes, so teammates who already pulled the branch are not forced to rewrite history.

3. How do I checkout a previous commit in Git?

Run git switch --detach commit-hash to inspect the tree at that commit without moving your branch. When you are done, run git switch main to return to normal development on the branch.

4. How do I rollback multiple commits in Git?

On a local-only branch, git reset --hard HEAD~N moves back N commits. On a shared branch, use git revert to create undo commits; see the Git revert guide for reverting several commits or ranges.

5. Can I recover a commit after resetting Git history?

Often yes. git reflog lists recent HEAD positions including commits removed by reset. Find the lost commit hash there and run git reset --hard that-hash to point your branch at it again.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)