SoFunction
Updated on 2025-03-04

Summary of six ways to undo changes in Git

When using Git for project code management, some errors or requirements will inevitably occur, and the code needs to be revoked or modified. Git provides a variety of ways to undo existing changes. This article will introduce 6 commonly used methods of undoing changes in Git to help you better deal with these issues!

Before you begin the example, create a simple Git repository containing some commits:

git init && \
echo {} >  && git add . && git commit -m "Add " && \
echo FOO=bar > .env && git add . && git commit -m "Add .env" && \
touch  && git add . && git commit -m "Add README" && \
touch .gitignore && git add . && git commit -m "Add .gitignore"

For these commands, the following historical operations are actually included:

* 4753e23 - (HEAD -> master) Add .gitignore (4 seconds ago) <AleksandrHovhannisyan>
* 893d18d - Add README (4 seconds ago) <AleksandrHovhannisyan>
* 2beb7c7 - Add .env (4 seconds ago) <AleksandrHovhannisyan>
* 0beebfb - Add  (5 seconds ago) <AleksandrHovhannisyan>

1. Modify the most recent submission

Created and submitted.gitignoreShortly after the file, I decided to modify this file:

echo node_modules > .gitignore

But don't want to add a commit record for such a minor change in the git log history. Or you need to correct a typo in the most recent commit message.

Both cases are usedgit amendClassic use cases for commands:

git commit -a --amend

Simply put, the git amend command is used to edit commit and submit messages in git. This is one of the most basic ways to undo changes in git.

When running the above code, git opens the selected editor and displays the most recent commit, adding changes to the staging environment:

Add .gitignore

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Sun Oct 11 08:25:58 2022 -0400
#
# On branch master
# Changes to be committed:
#       new file:   .gitignore
#

Save and close the file, git will modify the most recent commit to include new changes. You can also edit the submission message before saving the file.

If all you have to do is update the commit message itself, such as fixing a spelling error, it doesn't actually need to enter the temporary environment. Just run this command:

git commit --amend

Change the submission message in the editor and save the file, and close it.

After modifying the recent commit, the log will look like this:

* 7598875 - (HEAD -> master) Add .gitignore (31 seconds ago) <AleksandrHovhannisyan>
* 893d18d - Add README (79 seconds ago) <AleksandrHovhannisyan>
* 2beb7c7 - Add .env (79 seconds ago) <AleksandrHovhannisyan>
* 0beebfb - Add  (80 seconds ago) <AleksandrHovhannisyan>

Now, assume that the old commit has been pushed to the remote branch before the modification. If runninggit status, you will be told that there is a commit between the local branch and the remote branch:

On branch master
Your branch and 'origin/master' have diverged,
and have 1 and 1 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

This is also normal, because the remote branch has old commits, while the local branch has modified commits. Their hashes are different because modifying the commit changes its timestamp, which forces git to calculate the new hash. To update the remote branch with a new commit, you need to force it to push:git push -f. This will overwrite the remote branch's history with the local branch.

It should be noted that here we are forced pushing on our own branches, and in actual work, we should not force pushing to the public branch; if we do this, everyone's local master replica will be different from the remote replica, and any new features based on the old master will now have an incompatible commit history.

2. Reset the branch to an older commit

So far, we have the following submission history:

* 7598875 - (HEAD -> master) Add .gitignore (31 seconds ago) <AleksandrHovhannisyan>
* 893d18d - Add README (79 seconds ago) <AleksandrHovhannisyan>
* 2beb7c7 - Add .env (79 seconds ago) <AleksandrHovhannisyan>
* 0beebfb - Add  (80 seconds ago) <AleksandrHovhannisyan>

Let's add a commit to the master again:

touch file && git add . && git commit -m "Add a file"

Now the commit history has become like this:

* b494f6f - (HEAD -> master) Add a file (5 seconds ago) <AleksandrHovhannisyan>
* 7598875 - Add .gitignore (3 minutes ago) <AleksandrHovhannisyan>
* 893d18d - Add README (4 minutes ago) <AleksandrHovhannisyan>
* 2beb7c7 - Add .env (4 minutes ago) <AleksandrHovhannisyan>
* 0beebfb - Add  (4 minutes ago) <AleksandrHovhannisyan>

A few minutes later, for some reason, we decided not to keep the most recent commit anymore. To delete it, simply hard reset the commit before the HEAD pointer, which always points to the latest commit on the current branch:

git reset --hard HEAD~1

The tilde (~) is followed by a number to tell git how many times it should go back from the given commit (in this case the HEAD pointer). Since HEAD always points to the latest commit on the current branch, this tells git to perform a hard reset of the commits before the most recent commit.

The output result is as follows:

HEAD is now at 7598875 Add .gitignore

Hard reset is a convenient way to undo git changes, but it's a destructive process - all changes in that commit will be lost, and the only way to retrieve them is throughgit reflogCommand (more will be introduced later).

We can also reset to HEAD~nth commit, in which case all work during and after that commit will be lost:

git reset --hard HEAD~4

Or even a specific commit if it has a hash:

git reset --hard <hash-id>

Of course, it is not limited to resetting only for commits in the current branch. You can also reset the local branch to point to another local branch:

git reset --hard <someOtherBranch>

Even to the remote branch:

git reset --hard origin/master

This is useful, for example, if you accidentally submit content to the local master branch. Suppose that commit should be done on a feat/X branch, but forgot to create it, and keep submitting code to the local master.

Of course, we can also usegit cherry-pickLet’s solve this problem, but what if there are many submissions? It's a bit painful, and reset can be easily done.

To resolve this issue, you now need to create a feature branch:

git checkout -b feat/X

And forcefully reset the local master branch to the remote master branch:

git checkout master && git reset --hard origin/master

And don't forget to go back to the feature branch so that the same error will not be repeated:

git checkout feat/X

Soft reset branch

As mentioned above, if a hard reset is done, all the work done at or after that commit is lost. Of course, you can recover from that state, but additional operations are required. Instead, if you want to keep changes in git's staging environment, you can do a soft reset:

git reset --soft HEAD~1

Likewise, you can just use the commit hash instead of backtracking from the HEAD pointer:

git reset --soft a80951b

All changes introduced by this commit and any commits after it will appear in git's staging environment. Here, you can usegit reset HEAD file(s)Cancel the temporary file and make any required changes to the already temporary file. Then, any new commits can be made as needed.

Use cases:File A and File B were submitted in one commit, but then realized that they should actually be two separate commits. A soft reset can be performed and a file can be submitted selectively, and another file can be committed separately, all without losing any work.

Create a backup branch

We can use branches as backup mechanism in case you know a certain command that is about to run (e.g.git reset --hard) may corrupt the commit history of the branch. Before running these commands, you can simply create a temporary backup branch (e.g.git branch backup). If any problems occur, you can perform a hard reset for the backup branch:

git reset --hard backup

3. Interactive base

Git's interactive rebase is one of its most powerful and flexible commands, allowing rewinding history and making any required changes. If you want to delete old commits, change old commit messages, or compress old commits into other commits, then this is the command you need to use. All interactive changes begin withgit rebase -icommand, and a commit must be specified to reset the current branch.

Delete old commits

So far, we have the following submission history:

* 7598875 - (HEAD -> master) Add .gitignore (20 minutes ago) <AleksandrHovhannisyan>
* 893d18d - Add README (21 minutes ago) <AleksandrHovhannisyan>
* 2beb7c7 - Add .env (21 minutes ago) <AleksandrHovhannisyan>
* 0beebfb - Add  (21 minutes ago) <AleksandrHovhannisyan>

The second commit looks a bit suspicious, why check the local environment variable (.env) into git? Obviously, we need to delete this commit while keeping all other commits. To do this, we will run the interactive alternator for this commit:

git rebase -ir 2beb7c7^

This will bring up this editor:

pick 2beb7c7 Add .env
pick 893d18d Add README
pick 7598875 Add .gitignore

To remove 2beb7c7, you need to change the pick command to drop (or d) and leave the others unchanged:

drop 2beb7c7 Add .env
pick 893d18d Add README
pick 7598875 Add .gitignore

Now close and save the file, you will get the following confirmation:

Successfully rebased and updated refs/heads/master.

Now, if executedgit log, the commit will no longer be seen:

* 11221d4 - (HEAD -> master) Add .gitignore (6 seconds ago) <AleksandrHovhannisyan>
* 9ed001a - Add README (6 seconds ago) <AleksandrHovhannisyan>
* 0beebfb - Add  (50 minutes ago) <AleksandrHovhannisyan>

Note that all commit hashes after the deleted commit will be recalculated. Therefore, although the root commit remains as0beebfb, but all hashes after it have changed. As you have seen several times now, if this branch was previously pushed to the remote repository, the local branch and the remote branch will now be out of sync. Therefore, you only need to do a forced push to update the remote branch:

git push -f

Rewrite the submission message

Let's add two more commits, and the submission message is written casually:

* 094f8cb - (HEAD -> master) Do more stuff (1 second ago) <AleksandrHovhannisyan>
* 74dab36 - Do something idk (59 seconds ago) <AleksandrHovhannisyan>
* 11221d4 - Add .gitignore (3 minutes ago) <AleksandrHovhannisyan>
* 9ed001a - Add README (3 minutes ago) <AleksandrHovhannisyan>
* 0beebfb - Add  (53 minutes ago) <AleksandrHovhannisyan>

Now I want to modify these two submission messages. We will start with interactive transformation. Here we will target the last two commits:

git rebase -i HEAD~2

This will open the editor:

pick 74dab36 Do something idk
pick 094f8cb Do more stuff

Now, just replace any commit pick of which you want to change the message with r (or reward):

reword 74dab36 Do something idk
reword 094f8cb Do more stuff

Close and save the file, and for each commit you want to overwrite, git will open the editor, allowing editing of messages as if it is being modified.

Maybe do this on the first commit:

Update README with getting started instructions

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Sun Oct 11 09:17:41 2022 -0400
#
# interactive rebase in progress; onto 11221d4
# Last command done (1 command done):
#    reword 74dab36 Do something idk
# Next command to do (1 remaining command):
#    reword 094f8cb Do more stuff
# You are currently editing a commit while rebasing branch 'master' on '11221d4'.
#
# Changes to be committed:
#       modified:   
#

Do this the second time:

Add name and author to 

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# interactive rebase in progress; onto 11221d4
# Last commands done (2 commands done):
#    reword 74dab36 Do something idk
#    reword 094f8cb Do more stuff
# No commands remaining.
# You are currently rebasing branch 'master' on '11221d4'.
#
# Changes to be committed:
#       modified:   
#

We will get the following output confirmation:

[detached HEAD 665034d] Update README with getting started instructions
 Date: Sun Oct 11 09:17:41 2020 -0400
 1 file changed, 5 insertions(+)
[detached HEAD ba88fb0] Add name and author to 
 1 file changed, 4 insertions(+), 1 deletion(-)
Successfully rebased and updated refs/heads/master.

Now the commit history looks like this:

* ba88fb0 - (HEAD -> master) Add name and author to  (31 seconds ago) <AleksandrHovhannisyan>
* 665034d - Update README with getting started instructions (53 seconds ago) <AleksandrHovhannisyan>
* 11221d4 - Add .gitignore (6 minutes ago) <AleksandrHovhannisyan>
* 9ed001a - Add README (6 minutes ago) <AleksandrHovhannisyan>
* 0beebfb - Add  (56 minutes ago) <AleksandrHovhannisyan>

Edit old submissions

Editing a submission means going to that point in the history immediately after submission. This allows the commit to be modified and includes (or deletes) any changes you want.

So far, we have the following submission history:

* ba88fb0 - (HEAD -> master) Add name and author to  (31 seconds ago) <AleksandrHovhannisyan>
* 665034d - Update README with getting started instructions (53 seconds ago) <AleksandrHovhannisyan>
* 11221d4 - Add .gitignore (6 minutes ago) <AleksandrHovhannisyan>
* 9ed001a - Add README (6 minutes ago) <AleksandrHovhannisyan>
* 0beebfb - Add  (56 minutes ago) <AleksandrHovhannisyan>

Suppose you want to edit the root commit (0beebfb) and add a second file:

touch .yarnrc

We will use interactive rebases for this submission. In the special case of this edit root submission, we need to use--rootOptions:

git rebase -i --root

This opens the editor and displays the submissions in chronological order:

pick 0beebfb Add 
pick 9ed001a Add README
pick 11221d4 Add .gitignore
pick 665034d Update README with getting started instructions
pick ba88fb0 Add name and author to 

All we need to do is replace pick with edit for the first commit in that list:

edit 0beebfb Add 
pick 9ed001a Add README
pick 11221d4 Add .gitignore
pick 665034d Update README with getting started instructions
pick ba88fb0 Add name and author to 

Close and save the file, you should see this message from git:

Stopped at 0beebfb... Add 
You can amend the commit now, with

        git commit --amend

Once you are satisfied with your changes, run

        git rebase --continue

Let's run these two commands:

git add .yarnrc && git commit --amend

Now you only need to modify the commit, the editor should look like this:

Add 

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Sun Oct 11 08:25:57 2020 -0400
#
# interactive rebase in progress; onto 666364d
# Last command done (1 command done):
#    edit 0beebfb Add 
# Next commands to do (4 remaining commands):
#    pick 9ed001a Add README
#    pick 11221d4 Add .gitignore
# You are currently editing a commit while rebasing branch 'master' on '666364d'.
#
#
# Initial commit
#
# Changes to be committed:
#       new file:   .yarnrc
#       new file:   
#

Now change the message toInitialize npm packageSave and exit. Now, according to git's suggestion, you need to continue rebase:

git rebase --continue

Now, the commit history now looks like this:

* 436e421 - (HEAD -> master) Add name and author to  (6 seconds ago) <AleksandrHovhannisyan>
* beb7c13 - Update README with getting started instructions (6 seconds ago) <AleksandrHovhannisyan>
* 1c75f66 - Add .gitignore (6 seconds ago) <AleksandrHovhannisyan>
* 69c997b - Add README (6 seconds ago) <AleksandrHovhannisyan>
* 36210ec - Initialize npm package (56 seconds ago) <AleksandrHovhannisyan>

compression

Compression can merge n commits into one, making the commit history more compact. This is sometimes useful if a feature branch introduces a large number of commits and only wants the feature to be represented in the history as a single commit (called the squash-and-rebase workflow). However, if needed in the future, old commits will not be restored or modified, which may be undesirable in some cases.

Again, for reference, we have the following commit history:

* 436e421 - (HEAD -> master) Add name and author to  (6 seconds ago) <AleksandrHovhannisyan>
* beb7c13 - Update README with getting started instructions (6 seconds ago) <AleksandrHovhannisyan>
* 1c75f66 - Add .gitignore (6 seconds ago) <AleksandrHovhannisyan>
* 69c997b - Add README (6 seconds ago) <AleksandrHovhannisyan>
* 36210ec - Initialize npm package (56 seconds ago) <AleksandrHovhannisyan>

Here is a feature branch and add some commits:

git checkout -b feature && \
touch file1 && git add . && git commit -m "Add file1" && \
touch file2 && git add . && git commit -m "Add file2" && \
touch file3 && git add . && git commit -m "Add file3"

Now submit the history as follows:

* 6afa3ac - (HEAD -> feature) Add file3 (4 seconds ago) <AleksandrHovhannisyan>
* c16cbc6 - Add file2 (4 seconds ago) <AleksandrHovhannisyan>
* 0832e96 - Add file1 (4 seconds ago) <AleksandrHovhannisyan>
* 436e421 - (master) Add name and author to  (12 minutes ago) <AleksandrHovhannisyan>
* beb7c13 - Update README with getting started instructions (12 minutes ago) <AleksandrHovhannisyan>
* 1c75f66 - Add .gitignore (12 minutes ago) <AleksandrHovhannisyan>
* 69c997b - Add README (12 minutes ago) <AleksandrHovhannisyan>
* 36210ec - Initialize npm package (12 minutes ago) <AleksandrHovhannisyan>

We can compress all of these into one using the following command:

git rebase -i master

This resets the feature branch to the master branch. Note that master is a reference to a specific commit, just like any other commit:

* 436e421 - (HEAD -> master) Add name and author to  (6 seconds ago) <AleksandrHovhannisyan>

This is the same:

git rebase -i 436e421

Anyway, once any of these commands are run, git opens the editor:

pick 0832e96 Add file1
pick c16cbc6 Add file2
pick 6afa3ac Add file3

We'll compress the last two commits into the first commit, so we'llpickChange the command tosquash

pick 0832e96 Add file1
squash c16cbc6 Add file2
squash 6afa3ac Add file3

Save and exit, git will open the editor, notifying us that three commits will be merged:

# This is a combination of 3 commits.
# This is the 1st commit message:

Add file1

# This is the commit message #2:

Add file2

# This is the commit message #3:

Add file3

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Sun Oct 11 09:37:05 2020 -0400
#
# interactive rebase in progress; onto 436e421
# Last commands done (3 commands done):
#    squash c16cbc6 Add file2
#    squash 6afa3ac Add file3
# No commands remaining.
# You are currently rebasing branch 'feature' on '436e421'.
#
# Changes to be committed:
#       new file:   file1
#       new file:   file2
#       new file:   file3
#

You can now change Add file1 to Add files 1, 2, and 3, or any other commit message you want. Save and close the file, and the commit history is now very compact:

* b646cf6 - (HEAD -> feature) Add files 1, 2, and 3 (70 seconds ago) <AleksandrHovhannisyan>
* 436e421 - (master) Add name and author to  (14 minutes ago) <AleksandrHovhannisyan>
* beb7c13 - Update README with getting started instructions (14 minutes ago) <AleksandrHovhannisyan>
* 1c75f66 - Add .gitignore (14 minutes ago) <AleksandrHovhannisyan>
* 69c997b - Add README (14 minutes ago) <AleksandrHovhannisyan>
* 36210ec - Initialize npm package (15 minutes ago) <AleksandrHovhannisyan>

4. Restore Submission

The above learns two ways to delete commits from git history:

  • Reset the HEAD pointer soft or hard to commit before the commit range to be deleted.

  • Perform interactive rebase and change to any commits you do not want to retain.pickfordrop

Unfortunately, both methods rewrite the commit history. Using interactive baselinemasterDelete from the branch.envFiles as an example. If you do this in reality, likemasterDeleting commits on such a shared branch will cause some trouble, and everyone on the team must hard reset the local onemasterBranches to matchorigin/master

The problem arises when people are doing work on feature branches, especially if they are from old onesmasterBranch cut out - the deleted file still exists. The base is not working, because it may be reintroduced inmasterThe file deleted on the branch; similarly,masterMerging branches into feature branches also doesn't work, because git has no public history to resolve:

fatal: refusing to merge unrelated histories

This isgit revertThe reason for the occurrence. Unlike deleting a commit via a rebase or hard/soft reset, the revert command creates a new commit to undo any changes introduced by the target commit:

git revert <hash-id>

Assume thatmasterOn the branch, want to usebeb7c13Hash recovery commit:

* 436e421 - (HEAD -> master) Add name and author to  (8 hours ago) <AleksandrHovhannisyan>
* beb7c13 - Update README with getting started instructions (8 hours ago) <AleksandrHovhannisyan>
* 1c75f66 - Add .gitignore (8 hours ago) <AleksandrHovhannisyan>
* 69c997b - Add README (8 hours ago) <AleksandrHovhannisyan>
* 36210ec - Initialize npm package (8 hours ago) <AleksandrHovhannisyan>

To do this, execute the following command:

git revert beb7c13

Git will open the editor:

Revert "Update README with getting started instructions"

This reverts commit beb7c132882ff1e3214dbd380514559fed0ef38f.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Changes to be committed:
#       modified:   
#

Save and close the file, and then rungit logTo view history:

* e1e6e06 - (HEAD -> master) Revert "Update README with getting started instructions" (58 seconds ago) <AleksandrHovhannisyan>
* 436e421 - Add name and author to  (8 hours ago) <AleksandrHovhannisyan>
* beb7c13 - Update README with getting started instructions (8 hours ago) <AleksandrHovhannisyan>
* 1c75f66 - Add .gitignore (8 hours ago) <AleksandrHovhannisyan>
* 69c997b - Add README (8 hours ago) <AleksandrHovhannisyan>
* 36210ec - Initialize npm package (8 hours ago) <AleksandrHovhannisyan>

Note that the original commit still exists in the history and its hash is worth keeping. The only change is that a new commit was added at the top of the branch to restore the changes introduced by the previous commit, as if the initially introduced changes were manually removed. Obviously, using git revert is more reasonable than using manual operations.

Therefore, undoing a commit introduces an additional commit, which is therefore even more confusing than interactive rebase or reset. But this is not a very important issue. And, the benefit is that it does not destroy the public branch.

5. Check out the file

git checkoutCommands are another basic way to undo git changes. It has three purposes:

  • Create a new branch:git checkout -b <newBranch>

  • Switch to branch or commit:git checkout <existingBranch>

  • Recover different versions of files.

Here we will focus on the third purpose. If you have made unstaged changes to the local file, you can usecheckoutCommands easily undo these changes:

git checkout <pathspec>

here,<pathspec>can be any valid path specifier, for example:.For the current directory,path/to/file, even regular expressions.

This will clear all unstaged changes to the specified file and restore the unmodified version of the file for the current branch. This command does not affect staging files - it will only clear unstaging changes.

For example, if you want to clear all unstaged changes in the current directory and start from scratch, the easiest way is to usegit checkoutCommands and.As a path specification:

git checkout .

We can also usegit checkoutTo restore the local or remote version of the file. For example, you can check out remotemasterA file on the branch:

git checkout origin/master -- <pathspec>

The purpose of this command is to branch the remoteorigin/masterThe specified file on<pathspec>Check out to the local branch. This command overwrites the file with the file on the remote branch with the same name on the local branch, that is, replaces the version of the local branch with the version of the remote branch, thereby ensuring that the local branch remains in sync with the remote branch.

Similarly, you can also check out a file on another local branch:

git checkout localBranchName -- <pathspec>

6. Use Git Reflog

Reflog can be considered as git for git—like an internal record-keeping system that can track most operations.

reflog stands for "reference log": a series of snapshots of different states of the HEAD pointer over time. This means that any time a commit is introduced, deleted, or modified, or checked out a new branch, or rewrite the hash of an old commit, these changes will be recorded in the reflog. We will be able to go back in the past to undo changes that may not be needed, even if they seem irreversible.

View Git repositoryreflogThe method is as follows:

git reflog

For example, a new branch can be checked out on a feature branch, and git will record the activity:

git checkout -b feature2

Reflog:

b646cf6 (HEAD -> feature2, origin/feature, feature) HEAD@{0}: checkout: moving from feature to feature2

This is because the HEAD pointer is redirected from the header of the feature branch to the header of the new branch feature2.

If you dig deeperreflog, you can also view all the changes in this article:

b646cf6 (HEAD -> feature2, origin/feature, feature) HEAD@{0}: checkout: moving from feature to feature2
b646cf6 (HEAD -> feature2, origin/feature, feature) HEAD@{1}: rebase -i (finish): returning to refs/heads/feature
b646cf6 (HEAD -> feature2, origin/feature, feature) HEAD@{2}: rebase -i (squash): Add files 1, 2, and 3
f3def0a HEAD@{3}: rebase -i (squash): # This is a combination of 2 commits.
0832e96 HEAD@{4}: rebase -i (start): checkout 436e421
6afa3ac HEAD@{5}: commit: Add file3
c16cbc6 HEAD@{6}: commit: Add file2
0832e96 HEAD@{7}: commit: Add file1
436e421 (master) HEAD@{8}: checkout: moving from master to feature
436e421 (master) HEAD@{9}: rebase -i (finish): returning to refs/heads/master
436e421 (master) HEAD@{10}: rebase -i (pick): Add name and author to 
beb7c13 HEAD@{11}: rebase -i (pick): Update README with getting started instructions
1c75f66 HEAD@{12}: rebase -i (pick): Add .gitignore
69c997b HEAD@{13}: rebase -i (pick): Add README
36210ec HEAD@{14}: commit (amend): Initialize npm package
04ba759 HEAD@{15}: rebase -i (edit): Add 
2bef9d4 HEAD@{16}: rebase -i (edit): Add 
666364d HEAD@{17}: rebase -i (start): checkout 666364da6703fc41e23515b1777de5ac84c8ad5e
ba88fb0 HEAD@{18}: rebase -i (finish): returning to refs/heads/master
ba88fb0 HEAD@{19}: rebase -i (reword): Add name and author to 
665034d HEAD@{20}: rebase -i (reword): Update README with getting started instructions
74dab36 HEAD@{21}: rebase -i: fast-forward
11221d4 HEAD@{22}: rebase -i (start): checkout HEAD~2
094f8cb HEAD@{23}: commit: Do more stuff
74dab36 HEAD@{24}: commit: Do something idk
11221d4 HEAD@{25}: rebase -i (finish): returning to refs/heads/master
11221d4 HEAD@{26}: rebase -i (pick): Add .gitignore
9ed001a HEAD@{27}: rebase -i (pick): Add README
0beebfb HEAD@{28}: rebase -i (start): checkout 2beb7c7^
7598875 HEAD@{29}: reset: moving to HEAD~1
b494f6f HEAD@{30}: commit: Add a file
7598875 HEAD@{31}: commit (amend): Add .gitignore
4753e23 HEAD@{32}: commit: Add .gitignore
893d18d HEAD@{33}: commit: Add README
2beb7c7 HEAD@{34}: commit: Add .env
0beebfb HEAD@{35}: commit (initial): Add 

You can quickly view any of these states by checking these commit hashes:

git checkout <hash-id>

Alternatively, you can reset the branch to a point in the history:

git reset --soft 7598875

This will be the current onefeature2Branch soft reset to the following history:

* 7598875 - (HEAD -> feature2) Add .gitignore (84 minutes ago) <AleksandrHovhannisyan>
* 893d18d - Add README (85 minutes ago) <AleksandrHovhannisyan>
* 2beb7c7 - Add .env (85 minutes ago) <AleksandrHovhannisyan>
* 0beebfb - Add  (85 minutes ago) <AleksandrHovhannisyan>

It can even run another onereflogTo view the changes:

7598875 (HEAD -> feature2) HEAD@{0}: reset: moving to 7598875

If you do not want the local branch to be overwritten, you can run it again.reflogCommand and reset the branch to theHEAD

git reset --hard b646cf6

This returns to the previous state:

* b646cf6 - (HEAD -> feature2, origin/feature, feature) Add files 1, 2, and 3 (13 minutes ago) <AleksandrHovhannisyan>
* 436e421 - (master) Add name and author to  (26 minutes ago) <AleksandrHovhannisyan>
* beb7c13 - Update README with getting started instructions (26 minutes ago) <AleksandrHovhannisyan>
* 1c75f66 - Add .gitignore (26 minutes ago) <AleksandrHovhannisyan>
* 69c997b - Add README (26 minutes ago) <AleksandrHovhannisyan>
* 36210ec - Initialize npm package (27 minutes ago) <AleksandrHovhannisyan>

Git'sreflogThe command is useful in case of hard reset and losing all work, just check the reflog and reset to the point before the hard reset and it's easy to do it!

Finally, if you want to clean up the reflog for some reason, you can delete the rows from it using:

git reflog delete HEAD@{n}

WillnReplace withreflogAny rows deleted in  .HEAD@{0}Refers to the latest line in reflog,HEAD@{1}Refers to the previous line, and so on.

Summarize

This is the end of this article about the six ways to undo changes in Git. For more related content on undoing changes in Git, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!