Reputation: 49339
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?
Upvotes: 26938
Views: 15749327
Reputation: 1289
Here is the way, that wasn't mentioned yet:
1.Check your current branch(just to be sure where you are):
git branch --show-current
git update-ref HEAD HEAD~1
4.(Optional)If you need to keep changes from commit in your working directory,stash them before you do step 3, then pop them back:
git stash
git update-ref HEAD HEAD~1
git stash pop
Upvotes: 1
Reputation: 317
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
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'd like the changes to stay in your working directory but not staged for commit, use:
git reset HEAD~1
git reset --mixed HEAD~1
After running any of these commands, you can:
git commit -m "new message"
.Upvotes: 12
Reputation: 73645
$ git commit -m "Something terribly misguided" # (0: Your Accident)
$ git reset HEAD~ # (1)
# === If you just want to undo the commit, stop here! ===
[ edit files as necessary ] # (2)
$ git add . # (3)
$ git commit -c ORIG_HEAD # (4)
git reset
is the command responsible for the undo. It will undo your last commit while leaving your working tree (the state of your files on disk) untouched. You'll need to add them again before you can commit them again.git add
anything that you want to include in your new commit.reset
copied the old head to .git/ORIG_HEAD
; commit
with -c ORIG_HEAD
will open an editor, which initially contains the log message from the old commit and allows you to edit it. If you do not need to edit the message, you could use the -C
option.Alternatively, to edit the previous commit (or just its commit message), commit --amend
will add changes within the current index to the previous commit.
To remove (not revert) a commit that has been pushed to the server, rewriting history with git push origin main --force[-with-lease]
is necessary. It's almost always a bad idea to use --force
; prefer --force-with-lease
instead, and as noted in the git manual:
You should understand the implications of rewriting history if you amend a commit that has already been published.
You can use git reflog
to determine the SHA-1 for the commit to which you wish to revert. Once you have this value, use the sequence of commands as explained above.
HEAD~
is the same as HEAD~1
. The article What is the HEAD in git? is helpful if you want to uncommit multiple commits.
Upvotes: 29692
Reputation: 73
Please never use this command for delete commit, **This command will remove your all changes and commit. **
git reset --hard HEAD~1
If any incident your changes removed, use these steps:- git reflog
It will appear like this: HEAD@{1}: reset: moving to HEAD~1 HEAD@{2}: commit: your previous commit message
you can recover it using: git reset --hard
OTHERWISE for back your commit Always use --soft command:-
git reset --soft HEAD~1
or
use git reset HEAD~1 // Undo the commit, but keep your changes
Upvotes: 6
Reputation: 33
Maybe someone wants to use plumbing git commands for that. You can use git update-ref
First you have to know the hash of the previous commit (I will assume that you are in the branch main
). You can use git rev-parse
for that.
$ git rev-parse main^
6bffe1cb1ed66a052a5a3224d1a778a64f6c357f
Note that you can use main^
, main~
, main~1
, main^1
, to get the first parent commit. More about differences between ^
and ~
in the manual gitrevisions(7)
.
Then you have to update the branch main to points to the previous commit
$ git update-ref refs/heads/main 6bffe1cb1ed66a052a5a3224d1a778a64f6c357f
You can do that in one command
$ git update-ref refs/heads/main main^
Optionally, you can add the reason of the change to view the reason in git reflog
.
$ git update-ref -m "Undo an accidental commit" refs/heads/main main^
If main
is your current branch, then HEAD
is a symbolic reference to refs/heads/main
. So you can use
$ git update-ref HEAD HEAD^
If you want to delete the very first commit. You can simply delete the file .git/refs/heads/main
(and the logs .git/logs/refs/head/main
) or run the following command
git update-ref -d refs/heads/main
Upvotes: 2
Reputation:
I'd suggest using the VSCode editor; nowadays, it's quite straightforward to undo committed or unfinished code changes, even if they were accidentally committed.
Upvotes: 8
Reputation: 323
Another solution:
If we want to achieve with interactive mode using git rebase command: Run below command
git rebase -i HEAD~2
Note: Here, Number 2 indicates N last commits we want to see it on interactive prompt.
Then interactive window will open in editor. We can edit and save file.
pick 31de0dc6387 First commit message
pick e98b2fc43d3 Second commit message
# Rebase d2b363648d3..e98b2fc43d3 onto d2b363648d3 (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
# commit's log message, unless -C is used, in which case
# keep only this commit's message; -c is same as -C but
# opens the editor
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
There are various options, we can pick only those commits which we want, We can squash all commits into single commit or modify commit messages. Also, we can change the order of commits.
To undo changes we can remove the below line from editor and save file.
pick e98b2fc43d3 Second commit message
After removing second commit id:
pick 31de0dc6387 First commit message
# Rebase d2b363648d3..e98b2fc43d3 onto d2b363648d3 (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
# commit's log message, unless -C is used, in which case
# keep only this commit's message; -c is same as -C but
# opens the editor
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
Once you make the file change then save file and run below command
git rebase --continue
You can verify your changes with git log
command which will give you commits history.
Now, you can push your changes.
git push origin <branch>
Upvotes: 4
Reputation: 1243
There are two way to undo most recent local commits..
01. git reset --hard HEAD~1
02.git reset --hard <commit-1-id>
Both method can use for reset second, third ... commits as below
01. git reset --hard HEAD~2
02.git reset --hard <commit-2-id>
01. git reset --hard HEAD~3
02.git reset --hard <commit-3-id>
.... ....... n so on.
Upvotes: 6
Reputation: 210350
Undoing a commit is a little scary if you don't know how it works. But it's actually amazingly easy if you do understand. I'll show you the 4 different ways you can undo a commit.
Say you have this, where C is your HEAD and (F) is the state of your files.
(F)
A-B-C
↑
master
git reset --hard
You want to destroy commit C and also throw away any uncommitted changes. You do this:
git reset --hard HEAD~1
The result is:
(F)
A-B
↑
master
Now B is the HEAD. Because you used --hard
, your files are reset to their state at commit B.
git reset
Maybe commit C wasn't a disaster, but just a bit off. You want to undo the commit but keep your changes for a bit of editing before you do a better commit. Starting again from here, with C as your HEAD:
(F)
A-B-C
↑
master
Do this, leaving off the --hard
:
git reset HEAD~1
In this case the result is:
(F)
A-B-C
↑
master
In both cases, HEAD is just a pointer to the latest commit. When you do a git reset HEAD~1
, you tell Git to move the HEAD pointer back one commit. But (unless you use --hard
) you leave your files as they were. So now git status
shows the changes you had checked into C. You haven't lost a thing!
git reset --soft
For the lightest touch, you can even undo your commit but leave your files and your index:
git reset --soft HEAD~1
This not only leaves your files alone, it even leaves your index alone. When you do git status
, you'll see that the same files are in the index as before. In fact, right after this command, you could do git commit
and you'd be redoing the same commit you just had.
git reset --hard
and need to get that code backOne more thing: Suppose you destroy a commit as in the first example, but then discover you needed it after all? Tough luck, right?
Nope, there's still a way to get it back. Type this
git reflog
and you'll see a list of (partial) commit SHAs (that is, hashes) that you've moved around in. Find the commit you destroyed, and do this:
git checkout -b someNewBranchName shaYouDestroyed
You've now resurrected that commit. Commits don't actually get destroyed in Git for some 90 days, so you can usually go back and rescue one you didn't mean to get rid of.
Upvotes: 12922
Reputation: 2894
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
.
Upvotes: 18
Reputation: 49
You can use github desktop. After adding a commit it shows a popup to undo a commit. It is very easy to undo a latest commit from it
Upvotes: 3
Reputation: 1330
Before picking specific tools (commands), please pick what you need rather than blindly running commands.
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
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
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.
Upvotes: 25
Reputation: 4991
A simple step-by-step guide is as follows:
Destroy a commit and throw away any uncommitted changes
git reset --hard HEAD~1
Undo the commit, but keep your changes
git reset HEAD~1
Keep your files, and stage all changes back automatically
git reset --soft HEAD~1
Resurrect a commit you destroyed
git reflog # To find the sh
Upvotes: 107
Reputation: 6248
Use the below command. Let’s say you want to go to a previous commit which has commit ID SHA-1 hash value:
71e2e57458bde883a37b332035f784c6653ec509
Then you can point to this commit. It will not display any log message after this commit and all history will be erased after that.
git push origin +71e2e57458bde883a37b332035f784c6653ec509^:master
Upvotes: 5
Reputation: 1271
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.
Upvotes: 19
Reputation: 21079
This will add a new commit which deletes the added files.
git rm yourfiles/*.class
git commit -a -m "deleted all class files in folder 'yourfiles'"
Or you can rewrite history to undo the last commit.
Warning: this command will permanently remove the modifications to the .java
files (and any other files) that you committed -- and delete all your changes from your working directory:
git reset --hard HEAD~1
The hard reset
to HEAD-1
will set your working copy to the state of the commit before your wrong commit.
Upvotes: 1308
Reputation: 139
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.
Upvotes: 13
Reputation: 984
There are many ways to do it:
Git command to undo the last commit/ previous commits:
Warning: Do Not use --hard if you do not know what you are doing. --hard is too dangerous, and it might delete your files.
Basic command to revert the commit in Git is:
$ git reset --hard <COMMIT -ID>
or
$ git reset --hard HEAD~<n>
COMMIT-ID: ID for the commit
n: is the number of last commits you want to revert
You can get the commit id as shown below:
$ **git log --oneline**
d81d3f1 function to subtract two numbers
be20eb8 function to add two numbers
bedgfgg function to multiply two numbers
where d81d3f1 and be20eb8 are commit id.
Now, let's see some cases:
Suppose you want to revert the last commit 'd81d3f1'. Here are two options:
$ git reset --hard d81d3f1
or
$ git reset --hard HEAD~1
Suppose you want to revert the commit 'be20eb8':
$ git reset --hard be20eb8
For more detailed information, you can refer to and try out some other commands too for resetting the head to a specified state:
$ git reset --help
Upvotes: 155
Reputation: 21512
reset --soft
or reset --hard
?I am just adding two cents for @Kyralessa's answer:
If you are unsure what to use go for --soft
(I used this convention to remember it --soft for safe).
If you choose --hard
by mistake you will LOSE your changes as it wasn't before.
If you choose --soft
by mistake you can achieve the same results of --hard
by applying additional commands
git reset HEAD file.html
git checkout -- file.html
echo "some changes..." > file.html
git add file.html
git commit -m "wrong commit"
# I need to reset
git reset --hard HEAD~1 (cancel changes)
# OR
git reset --soft HEAD~1 # Back to staging
git reset HEAD file.html # back to working directory
git checkout -- file.html # cancel changes
Credits goes to @Kyralessa.
Upvotes: 166
Reputation: 5901
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.
Upvotes: 11
Reputation: 3721
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:
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.
Upvotes: 30
Reputation: 12329
"Reset the working tree to the last commit"
git reset --hard HEAD^
"Clean unknown files from the working tree"
git clean
see - Git Quick Reference
NOTE: This command will delete your previous commit, so use with caution! git reset --hard
is safer.
Upvotes: 300
Reputation: 4324
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".
A popup will be opened (see the screenshot below)
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.
Upvotes: 29
Reputation: 1239
OP: How do I undo the most recent local commits in Git? I accidentally committed the wrong files [as part of several commits].
There are several ways to "undo" as series of commits, depending on the outcome you're after. Considering the start case below, reset
, rebase
and filter-branch
can all be used to rewrite your history.
How can C1 and C2 be undone to remove the tmp.log
file from each commit?
In the examples below, absolute commit references are used, but it works the same way if you're more used to relative references (i.e. HEAD~2
or HEAD@{n}
).
reset
$ git reset --soft t56pi
With reset
, a branch can be reset to a previous state, and any compounded changes be reverted to the Staging Area, from where any unwanted changes can then be discarded.
Note: As reset
clusters all previous changes into the Staging Area, individual commit meta-data is lost. If this is not OK with you, chances are you're probably better off with rebase
or filter-branch
instead.
rebase
$ git rebase --interactive t56pi
Using an interactive rebase
each offending commit in the branch can be rewritten, allowing you to modify and discard unwanted changes. In the infographic above, the source tree on the right illustrates the state post rebase
.
Step-by-step
t56pi
)pick
with edit
. Save and close.HEAD
, remove the unwanted files, and create brand new commits.Note: With rebase
much of the commit meta data is kept, in contrast to the reset
alternative above. This is most likely a preferred option, if you want to keep much of your history but only remove the unwanted files.
filter-branch
$ git filter-branch --tree-filter 'rm -r ./tmp.log' t56pi..HEAD
Above command would filter out the file ./tmp.log
from all commits in the desired range t56pi..HEAD
(assuming our initial start case from above). See below illustration for clarity.
Similar to rebase
, filter-branch
can be used to wipe unwanted files from a subsection of a branch. Instead of manually editing each commit through the rebase process, filter-branch
can automatically preformed the desired action on each commit.
Note: Just like rebase
, filter-branch
would preserve the rest of the commit meta-data, by only discarding the desired file. Notice how C1 and C2 have been rewritten, and the log-file discarded from each commit.
Just like anything related to software development, there are multiple ways to achieve the same (or similar) outcome for a give problem. You just need to pick the one most suitable for your particular case.
Do note that all three alternatives above rewrites the history completely. Unless you know exactly what you're doing and have good communication within your team - only rewrite commits that have not yet been published remotely!
Source: All examples above are borrowed from this blog.
Upvotes: 33
Reputation: 142522
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
.
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:
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
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.
git rebase --no-autostash
as well.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
.
Upvotes: 28
Reputation: 8050
If you want to revert the last commit but still want to keep the changes locally that were made in the commit, use this command:
git reset HEAD~1 --mixed
Upvotes: 86
Reputation: 66
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
$ 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
$ git reset --hard 36212a4
HEAD is now at 36212a4 First commit, new title
$ 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
$ 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)
$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
Upvotes: 27
Reputation: 2065
Do as the following steps.
Step 1
Hit git log
From the list of log, find the last commit hash code and then enter:
Step 2
git reset <hash code>
Upvotes: 37
Reputation: 24378
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
Upvotes: 14
Reputation: 4681
What I do each time I need to undo a commit/commits are:
git reset HEAD~<n>
// the number of last commits I need to undo
git status
// optional. All files are now in red (unstaged).
Now, I can add & commit just the files that I need:
git add <file names> & git commit -m "message" -m "details"
git checkout <filename>
git push origin <branch name> -f
// use -f to force the push.Upvotes: 20