ℹ️ Skipped - page is already crawled
| Filter | Status | Condition | Details |
|---|---|---|---|
| HTTP status | PASS | download_http_code = 200 | HTTP 200 |
| Age cutoff | PASS | download_stamp > now() - 6 MONTH | 0 months ago |
| History drop | PASS | isNull(history_drop_reason) | No drop reason |
| Spam/ban | PASS | fh_dont_index != 1 AND ml_spam_score = 0 | ml_spam_score=0 |
| Canonical | PASS | meta_canonical IS NULL OR = '' OR = src_unparsed | Not set |
| Property | Value |
|---|---|
| URL | https://www.baeldung.com/ops/git-revert-commit |
| Last Crawled | 2026-04-10 12:57:58 (15 hours ago) |
| First Indexed | 2024-02-13 15:24:07 (2 years ago) |
| HTTP Status Code | 200 |
| Meta Title | Undo and Revert Commits in Git | Baeldung on Ops |
| Meta Description | Learn the safest way to undo or revert commits in a Git repository. |
| Meta Canonical | null |
| Boilerpipe Text | 1. Introduction
When using
Git
, we might often find ourselves needing to undo or revert a commit. Whether it’s a
rollback
to a specific point in time or a revert to a particularly troublesome commit, undoing and reverting can help ensure stability.
In this tutorial, we’ll go through the most common commands and methods to undo and revert commits in Git. In addition, we’ll discuss and demonstrate the subtle differences in the way these commands function.
2. Reviewing Old Commits With
git checkout
To start, we can review the state of a project at a particular commit by using the
git checkout
command. In particular, each commit has a unique SHA-1 identifying hash, which we can use with
git checkout
 in order to revisit any commit in the timeline.
Furthermore, to get the identifier of a given commit, we can show the
full history with the
git log
command:
$ git
log
--all --decorate --oneline --graph
In this case, we revisit a commit that has an identifying hash of
e0390cd8d75dc0f1115ca9f350ac1a27fddba67d
:
$ git checkout e0390cd8d75dc0f1115ca9f350ac1a27fddba67d
At this point, the working directory should match the exact state of the specified commit. Thus,
we can view the project in its historical state and edit files without worrying about losing the current project state
. Nothing we do here gets saved to the repository. We call this a
detached HEAD
state.
In fact, we can use
git checkout
on locally modified files to restore them to their
working copy
versions.
Now, let’s understand how we can change the current state of the repository.
3. Reverting a Commit With
git revert
To attempt to take back changes, we can use the
git revert
command. It’s important to remember that
this command isn’t a traditional undo operation: it inverts changes introduced by the commit and generates a new commit with the inverse content
.
In other words, the operation doesn’t revert to the previous state of a project by removing all subsequent commits, it simply undoes a single commit by applying its negative on the current state. This means that
we should only use
git revert
if we want to apply the inverse of a particular commit
.
Furthermore,
git revert
doesn’t move
ref
pointers to the commit that we’re reverting, which is in contrast to other undo commands such as
git checkout
and
git reset
. Instead, these commands move the
HEAD
 ref pointer to the specified commit.
Let’s go through an example of
revert
.
First, we create a basic repository and populate the working directory with a single file:
$
mkdir
git_revert_example
$
cd
git_revert_example/
$ git init .
$
touch
test_file
Next, we add content to the newly-created file and commit it:
$
echo
"Test content"
>> test_file
$ git add test_file
$ git commit -m
"Adding content to test file"
After that, we add more content to have another commit:
$
echo
"More test content"
>> test_file
$ git add test_file
$ git commit -m
"Adding more test content"
Once done, we check the current commitÂ
log
:
$ git
log
--all --decorate --oneline --graph
* 617f2d8 (HEAD -> master) Adding more
test
content
* e0390cd Adding content to
test
file
We can see the
HEAD
is currently at
617f2d8
, while the unique part of the older commit hash is
e0390cd
. Thus, we use the former with
revert
:
$ git revert 617f2d8
Now, we verify the contents of
test_file
:
$
cat
test_file
Test content
In this instance, we reverted the most recent commit.
4. Reverting to Previous Project State With
git reset
Reverting to a previous state in a Git repository can be achieved via the
git reset
command, which undoes more complex changes.
While
git reset
is similar in behavior to
git checkout
,
it doesn’t move the
HEAD
ref pointer
.
4.1. Invocation Types
It has three primary forms of invocation that relate to Git’s internal state management system:
–hard
–soft
–mixed
Understanding which invocation to use is crucial for using
git revert
correctly
.
To understand the different invocations, we look at Git’s internal state management system
,
also known as
the three trees of Git
:
working directory
: in sync with the local file system, represents immediate changes made to content in files and directories
staging index tree
: tracks changes in
the working directory,
in other words, changes that have been selected with
git add
to be stored in the next commit
commit history
:
git commit
command adds changes to a permanent snapshot that’s stored in the
commit history
Now, let’s go through each invocation ofÂ
reset
.
4.2.
–hard
Perhaps the most dangerous and frequently used option with this invocation is commit history
,
–hard
updates ref pointers to the specified commit. After this, the
staging index
and
working index
reset to match that of the specified commit. Any previously pending changes to the
staging index
and
working directory
reset to match the state of the
commit tree
. Notably,
we lose a
ny pending or uncommitted work in the
staging index
and
working index
.
Adding on to the example above, let’s commit some more content to the original file:
$
echo
"Text to be committed"
>> test_file
$ git add test_file
Now, we add, populate, and commit a brand new file to the repository:
$
touch
new_test_file
$ git add new_test_file
$ git commit -m
"More text added to test_file, added new_test_file"
Let’s say we then decide to revert to the first commit in the repository. We achieve this by running a
–hard
reset:
$ git reset --hard e0390cd
Git should let us know that the
HEAD
is now at the specified commit hash. Looking at the contents of
test_file
shows us that the
latest text additions aren’t present, and the
new_test_file
no longer exists
. This
data loss is irreversible
, so it’s critical that we understand how
–hard
works with the three trees.
4.3.
–soft
When invoking with
–soft
,
reset
updates the ref pointers and stops there. Thus, the
staging index
andÂ
working directory
remain in the same state.
In the previous example, the changes we committed to the
staging index
wouldn’t have been deleted if we had used the
–soft
 argument
. We can still commit the changes in the
staging index
.
4.3.
–mixed
Without an argument,Â
reset
uses the –mixed flag, which offers a middle ground between the
–soft
and
–hard
invocations. The
staging index
resets to the state of the specified commit and ref pointers update. Any undone changes from the
staging index
move to the
working directory
.
Using
–mixed
in the example above means that local changes to the files aren’t deleted. Unlike with
–soft
, however,
no changes remain within the
staging index
.
4.4. Using
HEAD~1
Commonly,Â
reset
 is used with the
HEAD~1
special reference
that points to the most recent commit relative to the current
HEAD
.
This is a convenient way to target perhaps the most usual commit used with a
reset
:
$ git reset --soft HEAD~1
In this case, we perform a soft reset to
HEAD~1
, keeping the current work.
There are some potential caveats to this method:
using
HEAD~1
instead of targeting a hash reduces the repository visibility and may lead to incorrect decisions (e.g.,
reset
instead of
checkout
)
since
HEAD
changes according to different actions, we should ensure it points to the correct commit before using special references with it
reset
itself moves theÂ
HEAD
Thus, although potentially useful,
HEAD
should be used with caution as a reference for
reset
.
5. Conclusion
In this article, we looked at ways to undo and revert Git commits.
A rudimentary way to summarize the methods discussed is that
git revert
is safe, while
git reset
 is dangerous
. As we saw in the example, there’s a possibility of losing work with
git reset
. Thus, with
git revert
, we should be able to safely undo a public commit, whereas
git reset
is tailored toward undoing local changes in the
working directory
and
staging index
.
Notably,
git reset
moves the
HEAD
ref pointer, whereas
git revert
simply reverts a commit and applies the undo via a new commit to the
HEAD
. As usual, it’s best to assume that other developers are reliant upon published commits. |
| Markdown | [](https://www.baeldung.com/ops/ "Baeldung")
- [](https://www.baeldung.com/ops/ "Baeldung")
- [Start Here](https://www.baeldung.com/ops/start-here)
- [Courses â–Ľâ–˛]()
- [Learn Java Collections Explore the Java Collections Framework and Algorithms](https://www.baeldung.com/courses/learn-java-collections-course)
- [Learn Spring From no experience to actually building stuff](https://www.baeldung.com/courses/learn-spring-course)
- [Learn Maven Simplify your build with Apache Maven](https://www.baeldung.com/courses/learn-maven-course)
- [View All Courses](https://www.baeldung.com/members/all-courses)
- [Pricing](https://www.baeldung.com/pricing)
- [About â–Ľâ–˛]()
- [Full Archive The high level overview of all the articles on the site.](https://www.baeldung.com/ops/full_archive)
- [About Baeldung About Baeldung.](https://www.baeldung.com/about)
# Undo and Revert Commits in Git
Last updated: February 6, 2024

Written by: [baeldung](https://www.baeldung.com/ops/author/baeldung "Posts by baeldung")
- [Git](https://www.baeldung.com/ops/category/git)
## 1\. Introduction
When using [Git](https://www.baeldung.com/ops/git-guide), we might often find ourselves needing to undo or revert a commit. Whether it’s a [rollback](https://www.baeldung.com/ops/git-guide#3-git-reset---rollback-to-the-specific-state) to a specific point in time or a revert to a particularly troublesome commit, undoing and reverting can help ensure stability.
In this tutorial, we’ll go through the most common commands and methods to undo and revert commits in Git. In addition, we’ll discuss and demonstrate the subtle differences in the way these commands function.
## 2\. Reviewing Old Commits With *git checkout*
To start, we can review the state of a project at a particular commit by using the *git checkout* command. In particular, each commit has a unique SHA-1 identifying hash, which we can use with *git checkout* in order to revisit any commit in the timeline.
Furthermore, to get the identifier of a given commit, we can show the [full history with the *git log*](https://www.baeldung.com/ops/git-log-reflog-specific-branch) command:
```
$ git log --all --decorate --oneline --graphCopy
```
In this case, we revisit a commit that has an identifying hash of *e0390cd8d75dc0f1115ca9f350ac1a27fddba67d*:
```
$ git checkout e0390cd8d75dc0f1115ca9f350ac1a27fddba67dCopy
```
At this point, the working directory should match the exact state of the specified commit. Thus, **we can view the project in its historical state and edit files without worrying about losing the current project state**. Nothing we do here gets saved to the repository. We call this a [*detached HEAD*](https://www.baeldung.com/ops/git-head-tag-checkout#detached-head-state) state.
In fact, we can use *git checkout* on locally modified files to restore them to their *working copy* versions.
Now, let’s understand how we can change the current state of the repository.
## 3\. Reverting a Commit With *git revert*
To attempt to take back changes, we can use the *git revert* command. It’s important to remember that **this command isn’t a traditional undo operation: it inverts changes introduced by the commit and generates a new commit with the inverse content**.
In other words, the operation doesn’t revert to the previous state of a project by removing all subsequent commits, it simply undoes a single commit by applying its negative on the current state. This means that **we should only use *git revert* if we want to apply the inverse of a particular commit**.
Furthermore, *git revert* doesn’t move [ref](https://www.baeldung.com/ops/git-commits-identification-tagging#git-commit-refs-references) pointers to the commit that we’re reverting, which is in contrast to other undo commands such as *git checkout* and *git reset*. Instead, these commands move the *HEAD* ref pointer to the specified commit.
**Let’s go through an example of *revert***.
First, we create a basic repository and populate the working directory with a single file:
```
Copy
```
Next, we add content to the newly-created file and commit it:
```
Copy
```
After that, we add more content to have another commit:
```
Copy
```
Once done, we check the current commit *log*:
```
Copy
```
We can see the *HEAD* is currently at *617f2d8*, while the unique part of the older commit hash is *e0390cd*. Thus, we use the former with *revert*:
```
$ git revert 617f2d8Copy
```
Now, we verify the contents of *test\_file*:
```
Copy
```
In this instance, we reverted the most recent commit.
## 4\. Reverting to Previous Project State With *git reset*
Reverting to a previous state in a Git repository can be achieved via the *git reset* command, which undoes more complex changes.
While *git reset* is similar in behavior to *git checkout*, **it doesn’t move the *HEAD* ref pointer**.
### 4\.1. Invocation Types
It has three primary forms of invocation that relate to Git’s internal state management system:
- *–hard*
- *–soft*
- *–mixed*
**Understanding which invocation to use is crucial for using *git revert* correctly**.
To understand the different invocations, we look at Git’s internal state management system*,* also known as [the three trees of Git](https://www.baeldung.com/ops/git-trees-commit-tree-navigation#git-trees):
1. *working directory*: in sync with the local file system, represents immediate changes made to content in files and directories
2. *staging index tree*: tracks changes in *the working directory,* in other words, changes that have been selected with *git add* to be stored in the next commit
3. *commit history*: *git commit* command adds changes to a permanent snapshot that’s stored in the *commit history*
Now, let’s go through each invocation of *reset*.
### 4\.2. *–hard*
**Perhaps the most dangerous and frequently used option with this invocation is commit history**, *–hard* updates ref pointers to the specified commit. After this, the *staging index* and *working index* reset to match that of the specified commit. Any previously pending changes to the *staging index* and *working directory* reset to match the state of the *commit tree*. Notably, **we lose a****ny pending or uncommitted work in the *staging index* and *working index***.
Adding on to the example above, let’s commit some more content to the original file:
```
Copy
```
Now, we add, populate, and commit a brand new file to the repository:
```
Copy
```
Let’s say we then decide to revert to the first commit in the repository. We achieve this by running a *–hard* reset:
```
$ git reset --hard e0390cdCopy
```
Git should let us know that the *HEAD* is now at the specified commit hash. Looking at the contents of *test\_file* shows us that the **latest text additions aren’t present, and the *new\_test\_file* no longer exists**. This **data loss is irreversible**, so it’s critical that we understand how *–hard* works with the three trees.
### 4\.3. *–soft*
When invoking with *–soft*, *reset* updates the ref pointers and stops there. Thus, the *staging index* and *working directory* remain in the same state.
**In the previous example, the changes we committed to the *staging index* wouldn’t have been deleted if we had used the *–soft* argument**. We can still commit the changes in the *staging index*.
### 4\.3. *–mixed*
Without an argument, *reset* uses the –mixed flag, which offers a middle ground between the *–soft* and *–hard* invocations. The *staging index* resets to the state of the specified commit and ref pointers update. Any undone changes from the *staging index* move to the *working directory*.
Using *–mixed* in the example above means that local changes to the files aren’t deleted. Unlike with *–soft*, however, **no changes remain within the *staging index***.
### 4\.4. Using *HEAD~1*
Commonly, *reset* is used with the [***HEAD~1***](https://www.baeldung.com/ops/git-commits-identification-tagging#2-special-refs) **[special reference](https://www.baeldung.com/ops/git-commits-identification-tagging#2-special-refs) that points to the most recent commit relative to the current *HEAD***.
This is a convenient way to target perhaps the most usual commit used with a *reset*:
```
$ git reset --soft HEAD~1Copy
```
In this case, we perform a soft reset to *HEAD~1*, keeping the current work.
There are some potential caveats to this method:
- using *HEAD~1* instead of targeting a hash reduces the repository visibility and may lead to incorrect decisions (e.g., *reset* instead of *checkout*)
- since *HEAD* changes according to different actions, we should ensure it points to the correct commit before using special references with it
- ***reset* itself moves the *HEAD***
Thus, although potentially useful, *HEAD* should be used with caution as a reference for *reset*.
## 5\. Conclusion
In this article, we looked at ways to undo and revert Git commits.
A rudimentary way to summarize the methods discussed is that ***git revert* is safe, while *git reset* is dangerous**. As we saw in the example, there’s a possibility of losing work with *git reset*. Thus, with *git revert*, we should be able to safely undo a public commit, whereas *git reset* is tailored toward undoing local changes in the *working directory* and *staging index*.
Notably, *git reset* moves the *HEAD* ref pointer, whereas *git revert* simply reverts a commit and applies the undo via a new commit to the *HEAD*. As usual, it’s best to assume that other developers are reliant upon published commits.

#### Categories
- [Jenkins](https://www.baeldung.com/ops/category/jenkins)
- [Kubernetes](https://www.baeldung.com/ops/category/kubernetes)
- [Git](https://www.baeldung.com/ops/category/git)
#### Series
- [Docker Guide](https://www.baeldung.com/ops/docker-guide)
- [Kubernetes Guide](https://www.baeldung.com/ops/kubernetes-series)
#### About
- [About Baeldung](https://www.baeldung.com/about)
- [Baeldung All Access](https://www.baeldung.com/courses)
- [The Full Archive](https://www.baeldung.com/ops/full_archive)
- [Editors](https://www.baeldung.com/editors)
- [Ebooks](https://www.baeldung.com/library)
- [FAQ](https://www.baeldung.com/library/faq)
- [Baeldung Pro](https://www.baeldung.com/members/)
- [Terms Of Service](https://www.baeldung.com/terms-of-service)
- [Privacy Policy](https://www.baeldung.com/privacy-policy)
- [Company Info](https://www.baeldung.com/baeldung-company-info)
- [Contact](https://www.baeldung.com/contact)
Privacy Manager


## Looks like your ad blocker is on.
Ă—
We rely on ads to keep creating quality content for you to enjoy for free.
Please support our site by disabling your ad blocker or, use **Baeldung Pro** for a clean, absolutely **no-ads** reading experience.
Disable
[Baeldung Pro](https://www.baeldung.com/members)
Continue without supporting us
#### Choose your Ad Blocker
- Adblock Plus
- Adblock
- Adguard
- Ad Remover
- Brave
- Ghostery
- uBlock Origin
- uBlock
- UltraBlock
- Other
1. In the extension bar, click the AdBlock Plus icon
2. Click the large blue toggle for this website
3. Click refresh
1. In the extension bar, click the AdBlock icon
2. Under "Pause on this site" click "Always"
1. In the extension bar, click on the Adguard icon
2. Click on the large green toggle for this website
1. In the extension bar, click on the Ad Remover icon
2. Click "Disable on This Website"
1. In the extension bar, click on the orange lion icon
2. Click the toggle on the top right, shifting from "Up" to "Down"
1. In the extension bar, click on the Ghostery icon
2. Click the "Anti-Tracking" shield so it says "Off"
3. Click the "Ad-Blocking" stop sign so it says "Off"
4. Refresh the page
1. In the extension bar, click on the uBlock Origin icon
2. Click on the big, blue power button
3. Refresh the page
1. In the extension bar, click on the uBlock icon
2. Click on the big, blue power button
3. Refresh the page
1. In the extension bar, click on the UltraBlock icon
2. Check the "Disable UltraBlock" checkbox
1. Please disable your Ad Blocker
Go Back |
| Readable Markdown | ## 1\. Introduction
When using [Git](https://www.baeldung.com/ops/git-guide), we might often find ourselves needing to undo or revert a commit. Whether it’s a [rollback](https://www.baeldung.com/ops/git-guide#3-git-reset---rollback-to-the-specific-state) to a specific point in time or a revert to a particularly troublesome commit, undoing and reverting can help ensure stability.
In this tutorial, we’ll go through the most common commands and methods to undo and revert commits in Git. In addition, we’ll discuss and demonstrate the subtle differences in the way these commands function.
## 2\. Reviewing Old Commits With *git checkout*
To start, we can review the state of a project at a particular commit by using the *git checkout* command. In particular, each commit has a unique SHA-1 identifying hash, which we can use with *git checkout* in order to revisit any commit in the timeline.
Furthermore, to get the identifier of a given commit, we can show the [full history with the *git log*](https://www.baeldung.com/ops/git-log-reflog-specific-branch) command:
```
$ git log --all --decorate --oneline --graph
```
In this case, we revisit a commit that has an identifying hash of *e0390cd8d75dc0f1115ca9f350ac1a27fddba67d*:
```
$ git checkout e0390cd8d75dc0f1115ca9f350ac1a27fddba67d
```
At this point, the working directory should match the exact state of the specified commit. Thus, **we can view the project in its historical state and edit files without worrying about losing the current project state**. Nothing we do here gets saved to the repository. We call this a [*detached HEAD*](https://www.baeldung.com/ops/git-head-tag-checkout#detached-head-state) state.
In fact, we can use *git checkout* on locally modified files to restore them to their *working copy* versions.
Now, let’s understand how we can change the current state of the repository.
## 3\. Reverting a Commit With *git revert*
To attempt to take back changes, we can use the *git revert* command. It’s important to remember that **this command isn’t a traditional undo operation: it inverts changes introduced by the commit and generates a new commit with the inverse content**.
In other words, the operation doesn’t revert to the previous state of a project by removing all subsequent commits, it simply undoes a single commit by applying its negative on the current state. This means that **we should only use *git revert* if we want to apply the inverse of a particular commit**.
Furthermore, *git revert* doesn’t move [ref](https://www.baeldung.com/ops/git-commits-identification-tagging#git-commit-refs-references) pointers to the commit that we’re reverting, which is in contrast to other undo commands such as *git checkout* and *git reset*. Instead, these commands move the *HEAD* ref pointer to the specified commit.
**Let’s go through an example of *revert***.
First, we create a basic repository and populate the working directory with a single file:
```
$ mkdir git_revert_example
$ cd git_revert_example/
$ git init .
$ touch test_file
```
Next, we add content to the newly-created file and commit it:
```
$ echo "Test content" >> test_file
$ git add test_file
$ git commit -m "Adding content to test file"
```
After that, we add more content to have another commit:
```
$ echo "More test content" >> test_file
$ git add test_file
$ git commit -m "Adding more test content"
```
Once done, we check the current commit *log*:
```
$ git log --all --decorate --oneline --graph
* 617f2d8 (HEAD -> master) Adding more test content
* e0390cd Adding content to test file
```
We can see the *HEAD* is currently at *617f2d8*, while the unique part of the older commit hash is *e0390cd*. Thus, we use the former with *revert*:
```
$ git revert 617f2d8
```
Now, we verify the contents of *test\_file*:
```
$ cat test_file
Test content
```
In this instance, we reverted the most recent commit.
## 4\. Reverting to Previous Project State With *git reset*
Reverting to a previous state in a Git repository can be achieved via the *git reset* command, which undoes more complex changes.
While *git reset* is similar in behavior to *git checkout*, **it doesn’t move the *HEAD* ref pointer**.
### 4\.1. Invocation Types
It has three primary forms of invocation that relate to Git’s internal state management system:
- *–hard*
- *–soft*
- *–mixed*
**Understanding which invocation to use is crucial for using *git revert* correctly**.
To understand the different invocations, we look at Git’s internal state management system*,* also known as [the three trees of Git](https://www.baeldung.com/ops/git-trees-commit-tree-navigation#git-trees):
1. *working directory*: in sync with the local file system, represents immediate changes made to content in files and directories
2. *staging index tree*: tracks changes in *the working directory,* in other words, changes that have been selected with *git add* to be stored in the next commit
3. *commit history*: *git commit* command adds changes to a permanent snapshot that’s stored in the *commit history*
Now, let’s go through each invocation of *reset*.
### 4\.2. *–hard*
**Perhaps the most dangerous and frequently used option with this invocation is commit history**, *–hard* updates ref pointers to the specified commit. After this, the *staging index* and *working index* reset to match that of the specified commit. Any previously pending changes to the *staging index* and *working directory* reset to match the state of the *commit tree*. Notably, **we lose a****ny pending or uncommitted work in the *staging index* and *working index***.
Adding on to the example above, let’s commit some more content to the original file:
```
$ echo "Text to be committed" >> test_file
$ git add test_file
```
Now, we add, populate, and commit a brand new file to the repository:
```
$ touch new_test_file
$ git add new_test_file
$ git commit -m "More text added to test_file, added new_test_file"
```
Let’s say we then decide to revert to the first commit in the repository. We achieve this by running a *–hard* reset:
```
$ git reset --hard e0390cd
```
Git should let us know that the *HEAD* is now at the specified commit hash. Looking at the contents of *test\_file* shows us that the **latest text additions aren’t present, and the *new\_test\_file* no longer exists**. This **data loss is irreversible**, so it’s critical that we understand how *–hard* works with the three trees.
### 4\.3. *–soft*
When invoking with *–soft*, *reset* updates the ref pointers and stops there. Thus, the *staging index* and *working directory* remain in the same state.
**In the previous example, the changes we committed to the *staging index* wouldn’t have been deleted if we had used the *–soft* argument**. We can still commit the changes in the *staging index*.
### 4\.3. *–mixed*
Without an argument, *reset* uses the –mixed flag, which offers a middle ground between the *–soft* and *–hard* invocations. The *staging index* resets to the state of the specified commit and ref pointers update. Any undone changes from the *staging index* move to the *working directory*.
Using *–mixed* in the example above means that local changes to the files aren’t deleted. Unlike with *–soft*, however, **no changes remain within the *staging index***.
### 4\.4. Using *HEAD~1*
Commonly, *reset* is used with the [***HEAD~1***](https://www.baeldung.com/ops/git-commits-identification-tagging#2-special-refs) **[special reference](https://www.baeldung.com/ops/git-commits-identification-tagging#2-special-refs) that points to the most recent commit relative to the current *HEAD***.
This is a convenient way to target perhaps the most usual commit used with a *reset*:
```
$ git reset --soft HEAD~1
```
In this case, we perform a soft reset to *HEAD~1*, keeping the current work.
There are some potential caveats to this method:
- using *HEAD~1* instead of targeting a hash reduces the repository visibility and may lead to incorrect decisions (e.g., *reset* instead of *checkout*)
- since *HEAD* changes according to different actions, we should ensure it points to the correct commit before using special references with it
- ***reset* itself moves the *HEAD***
Thus, although potentially useful, *HEAD* should be used with caution as a reference for *reset*.
## 5\. Conclusion
In this article, we looked at ways to undo and revert Git commits.
A rudimentary way to summarize the methods discussed is that ***git revert* is safe, while *git reset* is dangerous**. As we saw in the example, there’s a possibility of losing work with *git reset*. Thus, with *git revert*, we should be able to safely undo a public commit, whereas *git reset* is tailored toward undoing local changes in the *working directory* and *staging index*.
Notably, *git reset* moves the *HEAD* ref pointer, whereas *git revert* simply reverts a commit and applies the undo via a new commit to the *HEAD*. As usual, it’s best to assume that other developers are reliant upon published commits. |
| Shard | 144 (laksa) |
| Root Hash | 17258965353624827544 |
| Unparsed URL | com,baeldung!www,/ops/git-revert-commit s443 |