How do I revert a Git repository to a previous commit?
Categories:
How to Revert a Git Repository to a Previous Commit

Learn the essential Git commands – git reset
, git revert
, and git checkout
– to undo changes and restore your repository to a desired past state safely and effectively.
Accidentally introduced a bug? Need to undo a series of commits? Git provides powerful tools to navigate your project's history and revert to previous states. This article will guide you through the primary methods for undoing changes in Git: git reset
, git revert
, and git checkout
. Each command serves a different purpose and has distinct implications for your repository's history, especially when working in a collaborative environment.
Understanding Git's State and History
Before diving into the commands, it's crucial to understand how Git manages your project's state. Git tracks changes through a series of commits, each representing a snapshot of your project at a specific point in time. Your working directory contains the files you're currently editing, the staging area (or index) holds changes you've marked for the next commit, and the local repository stores your committed history. Understanding these states helps in choosing the right reversion strategy.
graph TD A[Working Directory] --> B{git add .} B --> C[Staging Area (Index)] C --> D{git commit -m "Message"} D --> E[Local Repository (HEAD)] E --> F[Remote Repository (git push)]
Git's three-tree architecture: Working Directory, Staging Area, and Local Repository.
Method 1: git reset
– Rewriting History
git reset
is a powerful command used to undo changes by moving the HEAD pointer and optionally modifying the staging area and working directory. It's often used to discard local changes or to uncommit commits. Because it rewrites history, git reset
should be used with caution, especially on branches that have been pushed to a shared remote repository, as it can cause conflicts for collaborators.
git reset --hard
on a branch that has been pushed to a remote repository can lead to significant issues for collaborators. Only use git reset --hard
on public branches if you fully understand the implications and have coordinated with your team.There are three main modes for git reset
:
1. git reset --soft <commit-hash>
Moves HEAD to the specified commit, but keeps the changes from the undone commits in your staging area. This means the changes are ready to be re-committed.
2. git reset --mixed <commit-hash>
(Default)
Moves HEAD to the specified commit and unstages the changes from the undone commits. The changes remain in your working directory, allowing you to modify them before staging and committing again.
3. git reset --hard <commit-hash>
Moves HEAD to the specified commit, and discards all changes from the undone commits from both the staging area and the working directory. This is a destructive operation, as all uncommitted changes and the changes from the undone commits will be lost.
# View your commit history to find the target commit hash
git log --oneline
# Example: Reset to a specific commit, keeping changes in staging
git reset --soft HEAD~1 # Resets to the commit before the last one
git reset --soft <commit-hash>
# Example: Reset to a specific commit, keeping changes in working directory
git reset --mixed HEAD~2 # Resets two commits back, unstaging changes
git reset --mixed <commit-hash>
# Example: Reset to a specific commit, discarding all changes
git reset --hard HEAD~3 # Resets three commits back, destroying changes
git reset --hard <commit-hash>
Examples of git reset
commands with different modes.
Method 2: git revert
– Creating New History
git revert
is the safest way to undo changes, especially on shared branches. Instead of rewriting history, git revert
creates a new commit that undoes the changes introduced by a previous commit. This means the original commit remains in the project history, and a new commit is added that effectively cancels out its effects. This approach preserves the integrity of the commit history, making it ideal for collaborative projects.
sequenceDiagram participant DevA as Developer A participant DevB as Developer B participant Repo as Remote Repository DevA->>Repo: git push (Commit C1) DevB->>Repo: git push (Commit C2) DevA->>Repo: git push (Commit C3 - introduced bug) Note over DevA,Repo: Bug discovered in C3 DevA->>DevA: git revert C3 DevA->>Repo: git push (Commit C4 - reverts C3) Note over DevA,Repo: History is preserved, C3 is undone by C4
How git revert
creates a new commit to undo changes, preserving history.
# View your commit history to find the commit to revert
git log --oneline
# Revert a specific commit (this will open your editor to write a commit message)
git revert <commit-hash>
# Revert a specific commit without opening an editor (uses default message)
git revert -m "Revert commit <commit-hash> due to bug" <commit-hash>
# Revert multiple commits (reverts them in reverse order of specification)
git revert <commit-hash-1> <commit-hash-2>
Examples of git revert
commands.
Method 3: git checkout
– Navigating History and Discarding Local Changes
git checkout
is primarily used for switching branches or restoring files to a previous state. While not a direct
revert
command in the sense of undoing commits, it's essential for navigating your repository's history and discarding uncommitted changes.
1. Discarding uncommitted changes in the working directory
If you've made changes to files but haven't staged or committed them, git checkout -- <file>
or git restore <file>
(Git 2.23+) can discard those changes and restore the file to its last committed state.
2. Restoring a file from a specific commit
You can restore a single file to how it looked in a previous commit without affecting the rest of your project's history. This is useful for retrieving an older version of a specific file.
3. Switching to a previous commit (detached HEAD state)
You can checkout
a specific commit to inspect the project at that point in time. This puts you in a 'detached HEAD' state, meaning you're not on any branch. Any new commits made in this state won't belong to a branch unless you explicitly create one.
# Discard uncommitted changes in a specific file
git checkout -- my_file.txt
# Or using git restore (Git 2.23+)
git restore my_file.txt
# Restore a file to its state in a previous commit
git checkout <commit-hash> -- my_file.txt
# Switch to a previous commit (detached HEAD)
git checkout <commit-hash>
# To return to your branch after a detached HEAD state
git checkout main # Or your branch name
Examples of git checkout
for file restoration and history navigation.
git checkout -b <new-branch-name>
before making new commits.