2278

Due to some bad cherry-picking, my local Git repository is currently five commits ahead of the origin, and not in a good state. I want to get rid of all these commits and start over again.

Obviously, deleting my working directory and re-cloning would do it, but downloading everything from GitHub again seems like overkill, and not a good use of my time.

Maybe git revert is what I need, but I don't want to end up 10 commits ahead of the origin (or even six), even if it does get the code itself back to the right state. I just want to pretend the last half-hour never happened.

Is there a simple command that will do this? It seems like an obvious use case, but I'm not finding any examples of it.


Note that this question is specifically about commits, not about:

  • untracked files
  • unstaged changes
  • staged, but uncommitted changes
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
David Moles
  • 48,006
  • 27
  • 136
  • 235
  • 3
    possible duplicate of [Various ways to remove local Git changes](http://stackoverflow.com/questions/22620393/various-ways-to-remove-local-git-changes) – spiderman Jun 12 '15 at 14:30

25 Answers25

3659

If your excess commits are only visible to you, you can just do git reset --hard origin/<branch_name> to move back to where the origin is. This will reset the state of the repository to the previous commit, and it will discard all local changes.

Doing a git revert makes new commits to remove old commits in a way that keeps everyone's history sane.

Yash
  • 6,644
  • 4
  • 36
  • 26
Ben Jackson
  • 90,079
  • 9
  • 98
  • 150
  • 143
    `git reset --hard ` if you want to go to a specific reference other than a remote branch. – Sam Soffes Jan 05 '14 at 00:51
  • 90
    This will not only discard local commits, but also throw away everything in your work tree (ie. you local files). If all you want to do is uncommit, but leave your work intact, you should do "git reset HEAD^" ... per http://stackoverflow.com/questions/2845731/how-to-uncommit-my-last-commit-in-git – aaronbauman Jan 28 '16 at 02:02
  • git reset --soft origin/ if you dont want to loose changes. as in case of --hard – bits Apr 14 '16 at 10:37
  • If there are local tags this won't get rid of those. I noticed this when a Maven release failed due to duplicate tag. – apa64 Oct 12 '16 at 13:22
  • 7
    You may want to do a Fetch after this. This fixed the number-of-commits-waiting-to-be-pushed counter on SourceTree. – Stan Apr 14 '17 at 07:05
  • 5
    `git reset --hard origin/` It will reset the project configuration as well, so take care of this. I have a big `.cfg` file which was reset to default. I had to spend hours on that again. – Ram Dec 06 '18 at 11:55
  • It's worth noting that this doesn't work if there is no remote for the branch/tracking branch. In that case you should utilize the commit hash solution that Sam Soffes mentions. – ryanwebjackson Nov 27 '19 at 16:10
  • 3
    Please update your answer to include that this will actually delete all the work you did also (like @aaronbauman mentioned back in 2016). I just lost a lot of work when all I wanted was to undo my last commit, without using `revert`, so that I could take out a sensitive value before pushing. – SeriousLee Jan 14 '22 at 19:37
  • @Ben Jackson: "This will reset the state of the repository" Do you mean the state of the repository or the current branch? Surely only the current branch is affected? – Matthew May 03 '23 at 02:30
  • You have saved me a lot of time. How wonderful. – Vương Hữu Thiện Jun 01 '23 at 08:35
561

Delete the most recent commit, without destroying the work you've done:

git reset --soft HEAD~1

Delete the most recent commit and remove changes:

git reset --hard HEAD~1

James L.
  • 12,893
  • 4
  • 49
  • 60
  • 17
    Useful answer. Thank you! I used git reset --soft origin/master – Tarun Kumar Aug 06 '18 at 10:40
  • 4
    @TarunKumar THANK YOU! I am using VS integration, and your solution was the only way I was able to wipe out a bunch of merge commits that I didn't want in a branch I didn't have permission to check in. – DVK Nov 13 '18 at 14:46
  • 2
    Thanks, just what I was looking for, "git reset --soft HEAD~1" did the work as I committed unintentionally and wanted to revert but had other files that I didn't want to be destroyed after revert. – Mate Ajdukovic Nov 28 '19 at 20:47
  • 2
    in Windows `--hard "HEAD@{1}"` – O-9 Nov 09 '20 at 15:57
  • last warning : `--hard` will **destroy un-commit local changes** – yurenchen Jan 20 '21 at 03:20
  • This answer was particularly useful, as I want to discard the last local commit without knowing its SHA1 hash. – martorad Sep 23 '21 at 11:25
  • 1
    Having the --soft answer come first in the answer above might help some overzealous StackExchange skimmers... nothing lost, no knowledge gained – charo Nov 07 '21 at 15:08
  • To me, this is the most useful answer, as I didn't want to get rid of changes, just a commit roll-back as I had mistakenly committed some large files. Also, worth noting, you can try doing a `git log` or `git status` before running the soft command to keep track of the current "HEAD". – Kingston Fortune Dec 19 '21 at 06:49
393

Simply delete your local master branch and recreate it like so:

git branch -D master
git checkout origin/master -b master
Ramon Zarazua B.
  • 7,195
  • 4
  • 22
  • 26
  • 4
    This works well when backtracking your changes would cost too much time, which happened to me after a couple of rebases. – aross May 15 '14 at 10:49
  • 1
    Useful for subtree pull/push problems among team members! – Jorge Orpinel Pérez Sep 11 '14 at 18:15
  • This is perfect when you want to restore a branch instead of just master. – Vladimir Ralev Nov 24 '14 at 06:36
  • Using egit in eclipse and this solution works perfect and its simple! – Cyborgz Jun 28 '16 at 12:31
  • 17
    this is not a good way to delete single local commit. Better to use `git reset --hard origin/` – Kirit Vaghela Sep 05 '16 at 06:18
  • @Gabox if your solution is big, you have a bigger problem than deleting and checking out the branch :) – Cristian E. Aug 07 '17 at 13:25
  • 1
    Maybe that solution will work, but that doesn't mean it's the proper one. – Adly May 06 '19 at 10:33
  • 1
    Thanks. Worked for me. I had to checkout another branch to be able to delete the master – Emil Mocan Jan 17 '20 at 11:31
  • This is the only one that worked for me, the other answers didn't work! I had pushed a change to remote, then I mistakenly thought I had pushed to the wrong branch - so I did a git revert on my local. But then i realized it was the correct branch after all, so i was stuck with an extra commit on local that even movign back a commit would still tell me my branch was 1 commit ahead. – Faraz Masroor Dec 15 '22 at 14:46
263

Try:

git reset --hard <the sha1 hash>

to reset your head to wherever you want to be. Use gitk to see which commit you want to be at. You can do reset within gitk as well.

Nicholas Shanks
  • 10,623
  • 4
  • 56
  • 80
Anders Zommarin
  • 7,094
  • 2
  • 25
  • 24
  • 8
    Upvoted this b/c it's useful information, but Ben Jackson's answer gets the checkmark for exactly solving what I wanted -- in a way that didn't require me to look up commit hashes. :) – David Moles Feb 23 '11 at 23:23
  • 2
    This is the one when your new branch has never been pushed to origin yet – Jan Oct 30 '18 at 16:13
83

On your branch attempt:

git reset --hard origin/<branch_name>

Validate the reversal (to the state, with no local commits), using "git log" or "git status" hence.

parasrish
  • 3,864
  • 26
  • 32
  • 1
    @Troyseph :all the answers listed above, I attempted as it is, and did not get the scenario fixed. The generic approach, which was not illustrated in any of the above answers, is what has been tried to answered here. – parasrish Apr 01 '16 at 18:10
  • 3
    The accepted answer is the same as yours, minus the generic branch name, and in the comments @Zoltan explicitly says `Just to be clear, if you're not working on master but on another branch, you should run git reset --hard origin/` – Troyseph Apr 04 '16 at 10:23
54

If you are using Atlassian SourceTree app, you could use the reset option in the context menu.

enter image description here

muruge
  • 4,083
  • 3
  • 38
  • 45
52

Simple Solution will be to match local master branch HEAD to origin/master branch HEAD

git reset --hard origin/master

PS: origin/master - is remote pointer to master branch. You can replace master with any branch name

narwanimonish
  • 1,552
  • 17
  • 13
40

TL;DR

on your branch

git reset --hard HEAD^ will throw away the last 1 local commit

git reset --hard HEAD~n will throw away the last n local commits

Marzieh Mousavi
  • 1,213
  • 1
  • 12
  • 28
37

You can use this git command

git reset --hard origin/<branch_name>
Lahcen
  • 1,231
  • 11
  • 15
34

git reset --hard @{u}* deletes all your local changes on the current branch, including commits. I'm surprised no one has posted this yet considering you won't have to look up what commit to revert to or play with branches.

* That is, reset to the current branch at @{upstream}—commonly origin/<branchname>, but not always

David Moles
  • 48,006
  • 27
  • 136
  • 235
Kevin Chen
  • 349
  • 3
  • 2
  • 2
    Some shells like fish will interpret the "@" so you may have to put the '@{u}' in quotes, e.g. `git reset --hard '@{u}'. Anyway, good find! – trysis Aug 14 '18 at 13:22
  • 2
    How do you print the value of @{u}? – Philip Rego Jun 27 '19 at 20:34
  • @PhilipRego `git name-rev @{u}` does the job if you're unsure of how current branch is configured for the push. Or maybe `git config -l | grep branch.$(git name-rev --name-only HEAD)` to more toroughly check the branch's config. – Romain Valeri Mar 02 '23 at 09:34
26

Before answering let's add some background, explaining what is this HEAD. since some of the options below will result in detached head

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 its 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 t go back

This will checkout 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.

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 the history as well.

# add 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

CodeWizard
  • 128,036
  • 21
  • 144
  • 167
18

Remove untracked files (uncommitted local changes)

git clean -df

Permanently deleting all local commits and get latest remote commit

git reset --hard origin/<branch_name>
ElasticCode
  • 7,311
  • 2
  • 34
  • 45
18

Use any number of times, to revert back to the last commit without deleting any files that you have recently created.

git reset --soft HEAD~1

Then use

git reset HEAD <name-of-file/files*>

to unstage, or untrack.

Jimut123
  • 474
  • 5
  • 14
16

I had a situation where I wanted to remove a commit that wasn't pushed, but the commit was before another one. To do so, I've used the following command

git rebase -i HEAD~2 -> it will rebase the last two commits

And I used 'drop' for the commit signature that I wanted to remove.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Robert
  • 19,800
  • 5
  • 55
  • 85
15

To see/get the SHA-1 id of the commit you want to come back too

gitk --all

To roll back to that commit

git reset --hard sha1_id

!Note. All the commits that were made after that commit will be deleted (and all your modification to the project). So first better clone the project to another branch or copy to another directory.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nicholas
  • 3,529
  • 2
  • 23
  • 31
  • this is great for situations where the remote is no longer available, and one simply needs to reset to some local commit. gitk is awesome - was not aware of it beforehand. – theRiley Sep 23 '16 at 03:11
  • If you're already in gitk you could as well simply right-click on the commit and select "reset branch XY to here". – mkrieger1 Oct 26 '16 at 08:52
  • And the newer commits won't immediately be deleted. There's just no branch pointing to them anymore (remember, a branch is nothing but a "bookmark" to a particular commit). – mkrieger1 Oct 26 '16 at 08:53
15

If Your branch is ahead of 'origin/XXX' by 5 commits.

You can issue:

git reset --hard HEAD~5

And it should remove the last 5 commits.

shizhen
  • 12,251
  • 9
  • 52
  • 88
Ha Choo
  • 153
  • 1
  • 5
11

For local commits which are not being pushed, you can also use git rebase -i to delete or squash a commit.

Nikhil Katre
  • 2,114
  • 23
  • 22
  • 1
    I know this may not be the shortest solution, but I upvoted you since IMHO `git rebase -i` is a more generic way to solve many similar problems and can be helpful in a variety of situations. – Stefan Marinov Jan 31 '17 at 14:48
  • 1
    Use the `drop` keyword (instead of deleting a line) when removing all commits to avoid having the rebase aborted. – Michal Čizmazia Jan 02 '19 at 12:27
6

For those interested in the Visual Studio solution, here is the drill:

  1. In the Team Explorer window, connect to the target repo.
  2. Then from Branches, right-click the branch of interest and select View history.
  3. Right-click a commit in the History window and choose Reset -> Delete changes (--hard).

That will throw away your local commits and reset the state of your repo to the selected commit. I.e. the changes after you pulled the repo will be lost.

UPDATE

The above procedure works fine up until VS2019; in VS2022 there is the New Git Experience. The workflow is similar but the UI is a bit different. Instead of Team Explorer, use Manage Branches from the Git menu. Now just click a branch on the left and its history is displayed on the right. Then go Right Click -> Reset -> Delete Changes (--hard)

Bozhidar Stoyneff
  • 3,576
  • 1
  • 18
  • 28
5

If you just want to throw away local commits and keep the modifications done in files then do
git reset @~
Other answers addressed the hard reset

Ashish Banker
  • 2,243
  • 3
  • 20
  • 21
5

Find the sha1 for the commit you want to revert to:

za$ git reflog
... snip ...
cf42fa2... HEAD@{0}: commit: fixed misc bugs
~
~
cf42fa2... HEAD@{84}: commit: fixed params for .....
73b9363... HEAD@{85}: commit: Don't symlink to themes on deployment.
547cc1b... HEAD@{86}: commit: Deploy to effectif.com web server.
1dc3298... HEAD@{87}: commit: Updated the theme.
18c3f51... HEAD@{88}: commit: Verify with Google webmaster tools.
26fbb9c... HEAD@{89}: checkout: moving to effectif

And then use --mixed flag so that you "reset HEAD and index":

za$ git reset --mixed cf42fa2

Available flags:

za$ git reset -h

-q, --quiet           be quiet, only report errors
--mixed               reset HEAD and index
--soft                reset only HEAD
--hard                reset HEAD, index and working tree
--merge               reset HEAD, index and working tree
--keep                reset HEAD but keep local changes
--recurse-submodules[=<reset>]
                      control recursive updating of submodules
-p, --patch           select hunks interactively
-N, --intent-to-add
z atef
  • 7,138
  • 3
  • 55
  • 50
3
git reset --hard <SHA-Code>

This will come in handy if you have made some mistakes on your local copy that you want to make sure doesn't get pushed to your remote branch by mistake.

The SHA-Code can be obtained by looking at webVersion of your git dashboard for the last commit on the branch.

This way you can get synchronized with the last commit on the branch.

You can do git pull after you have successfully completed the hard reset to confirm nothing new to syn i.e. you get to see the message.

Your branch is up to date with Origin/<Branch Name>

Samuel Philipp
  • 10,631
  • 12
  • 36
  • 56
1

Updated:

You can use new GIT LFS here: https://git-lfs.github.com/

git lfs migrate import --include="*.file_type"

then git push

Diep Tang
  • 37
  • 2
  • 11
1

You could look at using an interactive rebase with the drop command

So for say the last three commits...

git rebase -i HEAD~3

Swap out the pick commands

pick <hash1> Commit message 1
pick <hash2> Commit message 2
pick <hash3> Commit message 3

for drop commands

drop <hash1> Commit message 1
drop <hash2> Commit message 2
drop <hash3> Commit message 3
ActualAl
  • 1,192
  • 10
  • 13
0

If you get your local repo into a complete mess, then a reliable way to throw away local commits in Git is to...

  1. Use "git config --get remote.origin.url" to get URL of remote origin
  2. Rename local git folder to "my_broken_local_repo"
  3. Use "git clone <url_from_1>" to get fresh local copy of remote git repository

In my experience Eclipse handles the world changing around it quite well. However, you may need to select affected projects in Eclipse and clean them to force Eclipse to rebuild them. I guess other IDEs may need a forced rebuild too.

A side benefit of the above procedure is that you will find out if your project relies on local files that were not put into git. If you find you are missing files then you can copy them in from "my_broken_local_repo" and add them to git. Once you have confidence that your new local repo has everything you need then you can delete "my_broken_local_repo".

Adam Gawne-Cain
  • 1,347
  • 14
  • 14
0

For all unstaged changes git checkout -- .

for specific file git checkout -- path/to/file/to/revert