27143

I accidentally committed the wrong files to Git but haven't pushed the commit to the server yet.

How do I undo those commits from the local repository?

12
  • 3
    See this guide for Git commits undo on Local, Public and Git Branch How to undo Git Commits like pro Commented Feb 27, 2017 at 3:53
  • 198
    For VsCode users , just type ctrl +shift +G and then click on three dot ,ie , more options and then click on undo Last Commit Commented Apr 8, 2019 at 12:15
  • 5
    You can install git-extras which are a set of git utility functions - includes the git undo command to undo the most recent commit. I use it all of the time when I just committed something (and haven't pushed yet) and need to add an unstaged file or change the commit comment. Commented Jan 19, 2022 at 17:39
  • 2
    try with git diff + git apply Commented Dec 2, 2022 at 1:41
  • 3
    "undo" is the most vague question in codebase management with git. You need to specify where you want your code to be. git reset doc is a good starting point and reference. git reset --mixed is the default action for git reset, you should ponder upon the reason for this, thus you will have a clear expectation on codebase management before digging into git usage. Commented Mar 9, 2023 at 1:10

104 Answers 104

30

For sake of completeness, I will give the one glaringly obvious method that was overlooked by the previous answers.

Since the commit was not pushed, the remote was unchanged, so:

  1. Delete the local repository.
  2. Clone the remote repository.

This is sometimes necessary if your fancy Git client goes bye-bye (looking at you, egit).

Don't forget to re-commit your saved changes since the last push.

Sign up to request clarification or add additional context in comments.

Comments

29

I have found this site which describes how to undo things that you have committed into the repository.

Some commands:

git commit --amend # Change last commit git reset HEAD~1 --soft # Undo last commit 

Comments

29

Reference: How to undo last commit in Git?

If you have Git Extensions installed you can easily undo/revert any commit (you can download Git Extensions from here).

Open Git Extensions, right click on the commit you want to revert then select "Revert commit".

Git Extensions screen shot

A popup will be opened (see the screenshot below)

Revert commit popup

Select "Automatically create a commit" if you want to directly commit the reverted changes or if you want to manually commit the reverted changes keep the box un-selected and click on "Revert this commit" button.

Comments

28

The difference between git reset --mixed, --soft and --hard

Prerequisite: When a modification to an existing file in your repository is made, this change is initially considered as unstaged. In order to commit the changes, it needs to be staged which means adding it to the index using git add. During a commit operation, the files that are staged gets added to an index.

Let's take an example:

- A - B - C (master) 

HEAD points to C and the index matches C.

--soft

  • When we execute git reset --soft B with the intention of removing the commit C and pointing the master/HEAD to B.
  • The master/HEAD will now point to B, but the index still has changed from C.
  • When executing git status you could see the files indexed in commit C as staged.
  • Executing a git commit at this point will create a new commit with the same changes as C

--mixed

  • Execute git reset --mixed B.
  • On execution, master/HEAD will point to B and the index is also modified to match B because of the mixed flag used.
  • If we run git commit at this point, nothing will happen since the index matches HEAD.
  • We still have the changes in the working directory, but since they're not in the index, git status shows them as unstaged.
  • To commit them, you would git add and then commit as usual.

--hard

  • Execute git reset --hard B
  • On execution, master/HEAD will point to B and modifies your working directory
  • The changes added in C and all the uncommitted changes will be removed.
  • Files in the working copy will match the commit B, this will result in loosing permanently all changes which were made in commit C plus uncommitted changes

Hope this comparison of flags that are available to use with git reset command will help someone to use them wisely. Refer these for further details link1 & link2

Comments

28

Before answering, let's add some background, explaining what this HEAD is.

First of all what is HEAD?

HEAD is simply a reference to the current commit (latest) on the current branch.
There can only be a single HEAD at any given time (excluding git worktree).

The content of HEAD is stored inside .git/HEAD and it contains the 40 bytes SHA-1 of the current commit.


detached HEAD

If you are not on the latest commit - meaning that HEAD is pointing to a prior commit in history it's called detached HEAD.

Enter image description here

On the command line, it will look like this - SHA-1 instead of the branch name since the HEAD is not pointing to the tip of the current branch:

Enter image description here

Enter image description here


A few options on how to recover from a detached HEAD:


git checkout

git checkout <commit_id> git checkout -b <new branch> <commit_id> git checkout HEAD~X // x is the number of commits to go back 

This will checkout the new branch pointing to the desired commit.
This command will checkout to a given commit.
At this point, you can create a branch and start to work from this point on.

# Checkout a given commit. # Doing so will result in a `detached HEAD` which mean that the `HEAD` # is not pointing to the latest so you will need to checkout branch # in order to be able to update the code. git checkout <commit-id> # Create a new branch forked to the given commit git checkout -b <branch name> 

git reflog

You can always use the reflog as well.
git reflog will display any change which updated the HEAD and checking out the desired reflog entry will set the HEAD back to this commit.

Every time the HEAD is modified there will be a new entry in the reflog

git reflog git checkout HEAD@{...} 

This will get you back to your desired commit

Enter image description here


git reset --hard <commit_id>

"Move" your HEAD back to the desired commit.

# This will destroy any local modifications. # Don't do it if you have uncommitted work you want to keep. git reset --hard 0d1d7fc32 # Alternatively, if there's work to keep: git stash git reset --hard 0d1d7fc32 git stash pop # This saves the modifications, then reapplies that patch after resetting. # You could get merge conflicts if you've modified things which were # changed since the commit you reset to. 
  • Note: (Since Git 2.7) you can also use the git rebase --no-autostash as well.

enter image description here


git revert <sha-1>

"Undo" the given commit or commit range.
The reset command will "undo" any changes made in the given commit.
A new commit with the undo patch will be committed while the original commit will remain in history as well.

# Add a new commit with the undo of the original one. # The <sha-1> can be any commit(s) or commit range git revert <sha-1> 

This schema illustrates which command does what.
As you can see there, reset && checkout modify the HEAD.

Enter image description here

Comments

27

I validate an efficient method proposed, and here is a concrete example using it:

In case you want to permanently undo/cancel your last commit (and so on, one by one, as many as you want) three steps:

1: Get the id = SHA of the commit you want to arrive on with, of course

$ git log 

2: Delete your previous commit with

$ git reset --hard 'your SHA' 

3: Force the new local history upon your origin GitHub with the -f option (the last commit track will be erased from the GitHub history)

$ git push origin master -f 

Example

$ git log 

Last commit to cancel

commit e305d21bdcdc51d623faec631ced72645cca9131 (HEAD -> master, origin/master, origin/HEAD) Author: Christophe <[email protected]> Date: Thu Jul 30 03:42:26 2020 +0200 U2_30 S45; updating files package.json & yarn.lock for GitHub Web Page from docs/CV_Portfolio... 

Commit we want now on HEAD

commit 36212a48b0123456789e01a6c174103be9a11e61 Author: Christophe <[email protected]> Date: Thu Jul 30 02:38:01 2020 +0200 First commit, new title 

Reach the commit before by deleting the last one

$ git reset --hard 36212a4 HEAD is now at 36212a4 First commit, new title 

Check it's OK

$ git log commit 36212a48b0123456789e01a6c174103be9a11e61 (HEAD -> master) Author: Christophe <[email protected]> Date: Thu Jul 30 02:38:01 2020 +0200 First commit, new title $ git status On branch master Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded. (use "git pull" to update your local branch) nothing to commit, working tree clean 

Update your history on the Git(Hub)

$ git push origin master -f Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 To https://github.com/ GitUser bla bla/React-Apps.git + e305d21...36212a4 master -> master (forced update) 

Check it's all right

$ git status On branch master Your branch is up to date with 'origin/master'. nothing to commit, working tree clean 

Comments

26

HEAD:

Before reset commit we should know about HEAD... HEAD is nothing but your current state in your working directory. It is represented by a commit number.

Git commit:

Each change assigned under a commit which is represented by a unique tag. Commits can't be deleted. So if you want your last commit, you can simply dive into it using git reset.

You can dive into the last commit using two methods:

Method 1: (if you don't know the commit number, but want to move onto the very first)

git reset HEAD~1 # It will move your head to last commit 

Method 2: (if you know the commit you simply reset onto your known commit)

git reset 0xab3 # Commit number

Note: if you want to know a recent commit try git log -p -1

Here is the graphical representation:

Enter image description here

Comments

25

Before picking specific tools (commands), please pick what you need rather than blindly running commands.

Amending the commit

  • Just in case you want to edit your last commit, there is a command.

  • Advantage: It allows you to correct the last commit's message as well as add more changes to it.

    git commit --amend 

Resetting the Commit

  • Really want to undo the last commit (because of massive changes or you want to discard it all).

  • Advantage: The reset command will return to the one before the current revision, effectively making the last commit undone.

A. Soft Reset

Advantage: A soft flag. It guarantees the preservation of modifications made in undone revisions. The changes appear in your working copy as uncommitted local modifications once you run the command.

git reset --soft HEAD~1 

B. Hard Reset

Advantage: If you don't want to keep these changes, simply use the --hard flag. Be sure to only do this when you're sure you don't need these changes anymore.

git reset --hard HEAD~1 

Undo last commit but keep changes made to the files

Advantage:

This command will tell Git to advance the HEAD pointer back one commit. The files' modifications won't be impacted, though. Now, if you run git status, you ought to still be able to view the local file changes.

git reset HEAD~1 

Use according to your needs.

Comments

24

Just use git reset --hard <last good SHA> to reset your changes and give new commit. You can also use git checkout -- <bad filename>.

Comments

23
git reset --soft HEAD~1 git status 

Output

On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)

Changes to be committed:
(use "git restore --staged ..." to unstage) new file: file1

git log --oneline --graph 

Output

  • 90f8bb1 (HEAD -> master) Second commit \
  • 7083e29 Initial repository commit \

Comments

23

If you would like to eliminate the wrong files you should do

git reset --soft <your_last_good_commit_hash_here> Here, if you do git status, you will see the files in the staging area. You can select the wrong files and take them down from the staging area.

Like the following.

git reset wrongFile1 wrongFile2 wrongFile3

You can now just add the files that you need to push,

git add goodFile1 goodFile2

Commit them

git commit -v or git commit -am "Message"

And push

git push origin master

However, if you do not care about the changed files you can hard reset to previous good commit and push everything to the server.

By

git reset --hard <your_last_good_commit_hash_here> 

git push origin master

If you already published your wrong files to the server, you can use the --force flag to push to the server and edit the history.

git push --force origin master

Comments

23

To undo the last commit in Git but keep the changes in your working directory, you can use the following command:

git reset --soft HEAD~1 

Explanation:

  • git reset: This command undoes commits.
  • --soft: It undoes the commit but leaves the changes staged (ready for the next commit).
  • HEAD~1: This specifies the last commit (one commit before HEAD).

If you also want to unstage the changes:

If you'd like the changes to stay in your working directory but not staged for commit, use:

git reset HEAD~1 

If you just want to keep the changes in the working directory:

git reset --mixed HEAD~1 

After running any of these commands, you can:

  • Edit the changes.
  • Recommit with git commit -m "new message".

3 Comments

What is new in this answer compared to all answers already given here?
It's nice and easy to read. Sure the information is available elsewhere, but this is a concise explanation.
Very good answers. Also, I want to add about: git reset --hard HEAD [commit] In case you want to reset and jump back to a specific commit. This is good when you want to reset 2 or more commits. You can also check and bookmark this free git cheat-sheet here: git-cheat-sheet.jrguazon.com
20

Rebasing and dropping commits are the best when you want to keep the history clean useful when proposing patches to a public branch etc.

If you have to drop the topmost commit then the following one-liner helps

git rebase --onto HEAD~1 HEAD 

But if you want to drop 1 of many commits you did say

a -> b -> c -> d -> master

and you want to drop commit 'c'

git rebase --onto b c 

This will make 'b' as the new base of 'd' eliminating 'c'

Comments

20

In IntelliJ IDEA you can just open the Git repository log by pressing Alt+9, right mouse button click at some tag from the commits list, and select: "Reset Current Branch to Here...".

Comments

20

What I do each time I need to undo a commit/commits are:

  1. git reset HEAD~<n> // the number of last commits I need to undo

  2. git status // optional. All files are now in red (unstaged).

  3. Now, I can add & commit just the files that I need:

  • git add <file names> & git commit -m "message" -m "details"
  1. Optional: I can rollback the changes of the rest files, if I need, to their previous condition, with checkout:
  • git checkout <filename>
  1. if I had already pushed it to remote origin, previously:
  • git push origin <branch name> -f // use -f to force the push.

Comments

19

enter image description here

Assuming you're working in Visual Studio, if you go in to your branch history and look at all of your commits, simply select the event prior to the commit you want to undo, right-click it, and select Revert. Easy as that.

Comments

18

To undo the last local commit, without throwing away its changes, I have this handy alias in ~/.gitconfig

[alias] undo = reset --soft HEAD^ 

Then I simply use git undo which is super-easy to remember.

Comments

18

I wrote about this ages ago after having these same problems myself:

How to delete/revert a Git commit

Basically you just need to do:

git log, get the first seven characters of the SHA hash, and then do a git revert <sha> followed by git push --force.

You can also revert this by using the Git revert command as follows: git revert <sha> -m -1 and then git push.

Comments

17

Find the last commit hash code by seeing the log by:

git log 

Then

git reset <the previous co> 

Comments

15

Try this, hard reset to previous commit where those files were not added, then:

git reset --hard <commit_hash> 

Make sure you have a backup of your changes just in case, as it's a hard reset, which means they'll be lost (unless you stashed earlier)

Comments

15

Replace your local version, including your changes with the server version. These two lines of code will force Git to pull and overwrite local.

Open a command prompt and navigate to the Git project root. If you use Visual Studio, click on Team, Sync and click on "Open Command Prompt" (see the image) below.

Visual Studio

Once in the Cmd prompt, go ahead with the following two instructions.

git fetch --all 

Then you do

git reset --hard origin/master 

This will overwrite the existing local version with the one on the Git server.

Comments

15

If you simply want to trash all your local changes/commits and make your local branch look like the origin branch you started from...

git reset --hard origin/branch-name 

Comments

13

If you want to undo the very first commit in your repo

You'll encounter this problem:

$ git reset HEAD~ fatal: ambiguous argument 'HEAD~': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git <command> [<revision>...] -- [<file>...]' 

The error occurs because if the last commit is the initial commit (or no parents) of the repository, there is no HEAD~.

Solution

If you want to reset the only commit on "master" branch

$ git update-ref -d HEAD $ git rm --cached -r . 

Comments

13

You can use git revert <commit-id>.

And for getting the commit ID, just use git log.

Comments

13

If you have made local commits that you don't like, and they have not been pushed yet you can reset things back to a previous good commit. It will be as if the bad commits never happened. Here's how:

In your terminal (Terminal, Git Bash, or Windows Command Prompt), navigate to the folder for your Git repo. Run git status and make sure you have a clean working tree. Each commit has a unique hash (which looks something like 2f5451f). You need to find the hash for the last good commit (the one you want to revert back to). Here are two places you can see the hash for commits: In the commit history on GitHub or Bitbucket or website. In your terminal (Terminal, Git Bash, or Windows Command Prompt) run the command git log --online Once you know the hash for the last good commit (the one you want to revert back to), run the following command (replacing 2f5451f with your commit's hash):

git reset 2f5451f git reset --hard 2f5451f 

NOTE: If you do git reset the commits will be removed, but the changes will appear as uncommitted, giving you access to the code. This is the safest option because maybe you wanted some of that code and you can now make changes and new commits that are good. Often though you'll want to undo the commits and throw away the code, which is what git reset --hard does.

Comments

12

How to edit an earlier commit

Generally I don't want to undo a bunch of commits, but rather edit an earlier commit to how I wish I had committed it in the first place.

I found myself fixing a past commit frequently enough that I wrote a script for it.

Here's the workflow:

  1. git commit-edit <commit-hash> 

    This will drop you at the commit you want to edit.

    The changes of the commit will be unstaged, ready to be staged as you wish it was the first time.

  2. Fix and stage the commit as you wish it had been in the first place.

    (You may want to use git stash save --keep-index to squirrel away any files you're not committing)

  3. Redo the commit with --amend, eg:

    git commit --amend 
  4. Complete the rebase:

    git rebase --continue 

Call this following git-commit-edit and put it in your $PATH:

#!/bin/bash # Do an automatic git rebase --interactive, editing the specified commit # Revert the index and working tree to the point before the commit was staged # https://stackoverflow.com/a/52324605/5353461 set -euo pipefail script_name=${0##*/} warn () { printf '%s: %s\n' "$script_name" "$*" >&2; } die () { warn "$@"; exit 1; } [[ $# -ge 2 ]] && die "Expected single commit to edit. Defaults to HEAD~" # Default to editing the parent of the most recent commit # The most recent commit can be edited with `git commit --amend` commit=$(git rev-parse --short "${1:-HEAD~}") # Be able to show what commit we're editing to the user if git config --get alias.print-commit-1 &>/dev/null; then message=$(git print-commit-1 "$commit") else message=$(git log -1 --format='%h %s' "$commit") fi if [[ $OSTYPE =~ ^darwin ]]; then sed_inplace=(sed -Ei "") else sed_inplace=(sed -Ei) fi export GIT_SEQUENCE_EDITOR="${sed_inplace[*]} "' "s/^pick ('"$commit"' .*)/edit \\1/"' git rebase --quiet --interactive --autostash --autosquash "$commit"~ git reset --quiet @~ "$(git rev-parse --show-toplevel)" # Reset the cache of the toplevel directory to the previous commit git commit --quiet --amend --no-edit --allow-empty # Commit an empty commit so that that cache diffs are un-reversed echo echo "Editing commit: $message" >&2 echo 

Comments

11
$ git commit -m 'Initial commit' $ git add forgotten_file $ git commit --amend 

It’s important to understand that when you’re amending your last commit, you’re not so much fixing it as replacing it entirely with a new, improved commit that pushes the old commit out of the way and puts the new commit in its place. Effectively, it’s as if the previous commit never happened, and it won’t show up in your repository history.

The obvious value to amending commits is to make minor improvements to your last commit, without cluttering your repository history with commit messages of the form, “Oops, forgot to add a file” or “Darn, fixing a typo in last commit”.

2.4 Git Basics - Undoing Things

1 Comment

What if we wanted to revert a single file?
11
git reset --soft HEAD~1 

Soft: This will remove the commit from local only and keep the changes done in files as it is.

 git reset --hard HEAD~1 git push origin master 

Hard: This will remove that commit from local and remote and remove changes done in files.

Comments

10

I usually first find the commit hash of my recent commit:

git log 

It looks like this: commit {long_hash}

Copy this long_hash and reset to it (go back to same files/state it was on that commit):

git reset --hard {insert long_hash without braces} 

1 Comment

Notice the ``--hard option` will discard all changes not allowing us to discard only some files
10

Visual Studio Code makes this very easy.

VS Code

2 Comments

And this wasn't covered by one of the previous 151 answers (not a rhetorical question)? (Including deleted answers). In any case, you could make an (annotated) list of links to similar answers (as 152 answers (including deleted answer) as 6 long, long pages makes it difficult to navigate) to make navigation easier - say the ones that contain solutions using Visual Studio Code. (30 synonyms for Visual Studio Code have been observed in the wild so far.)
No, it was not.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.