How do I delete unpushed git commits?
Asked Answered
E

7

1532

I accidentally committed to the wrong branch. How do I delete that commit?

Enter answered 7/7, 2010 at 17:47 Comment(0)
P
2911

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

git reset --soft HEAD~1

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

git reset --hard HEAD~1
Prestissimo answered 7/7, 2010 at 17:50 Comment(15)
make sure HEAD is pointing at the branch.. (check it out first)Osullivan
And make sure HEAD~1 is the commit... You could also do git reset --hard originMilburn
Thought git remote lists origin for me, git reset --hard origin says fatal: ambiguous argument 'origin': unknown revision or path not in the working tree.. Why?Selachian
git reset HEAD~1 will also keep all your changes but will leave you with an empty index rather than keep everything (as the --soft option would).Psalter
Just as additional info, you can use HEAD^ instead of HEAD~1. The result will be the same as soon as the HEAD is pointing at the right palce ;-)Twist
The --hard option just blew up all of my unpushed commits, instead of just the most recent one. No thanks...Grof
Why was this upvoted? It's completely wrong and doesn't answer OP's question. Running git log HEAD@{1} -1 will still show you the commit you supposedly "destroyed".Shabuoth
For first commit: git reset origin/masterKatonah
@MikhailT. I'm sure it wont help you anymore, but lost commits can be found doing git reflogKatonah
@Selachian if you get the "ambiguous origin" error, you need to specify the branch like- git reset --hard origin/feature/my-cool-stuffAlltime
NOTE: That actually modifies your folder locally. If you want to just remove commit but not make any changes to your work use: git reset HEAD~1 --softSenatorial
Another option is the one I use. "git rebase -i", delete the commit(s), and add "noop" as the only action. Without the noop rebase makes no changes. I like this way, because I see exactly what I'm removing.Loeb
This actually removed the work for me (with --soft) --'Lit
worked for me, git reset --soft HEAD~2 (2 insted 1) then git pull and all ok ! thank you !Kirghiz
beware, git bisect reset seems to do the same thing. I lost commits I had not yet pushed to the remote repo.Doby
S
546

I wonder why the best answer that I've found is only in the comments! (by Daenyth with 86 up votes)

git reset --hard origin

This command will sync the local repository with the remote repository getting rid of every change you have made on your local. You can also do the following to fetch the exact branch that you have in the origin as Cleary suggested in the comments.

git reset --hard origin/<branch>
Sanhedrin answered 23/1, 2019 at 8:54 Comment(5)
Thanks for this, expanding the explanation slightly: for a specific branch: git reset --hard origin/<branch>Polyzoic
Or git reset --soft origin/<branch>, if you want to get rid of the commit but keep the local work.Trant
i get fatal: ambiguous argument 'origin': unknown revision or path not in the working tree., you need to specify the branch like: git reset --hard origin/feature/my-cool-stuffAlltime
Brilliant! This actually works, unlike the "accepted" answer which just detaches the head and leaves you hanging.Retinitis
How do you link to a comment?Martinmartina
K
66

Don't delete it: for just one commit git cherry-pick is enough.

But if you had several commits on the wrong branch, that is where git rebase --onto shines:

Suppose you have this:

 x--x--x--x <-- master
           \
            -y--y--m--m <- y branch, with commits which should have been on master

, then you can mark master and move it where you would want to be:

 git checkout master
 git branch tmp
 git checkout y
 git branch -f master

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- y branch, master branch

, reset y branch where it should have been:

 git checkout y
 git reset --hard HEAD~2 # ~1 in your case, 
                         # or ~n, n = number of commits to cancel

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- master branch
                ^
                |
                -- y branch

, and finally move your commits (reapply them, making actually new commits)

 git rebase --onto tmp y master
 git branch -D tmp


 x--x--x--x--m'--m' <-- master
           \
            -y--y <- y branch
Ketchup answered 7/7, 2010 at 17:58 Comment(2)
unfortunately, that was not the question.Raneeraney
@Raneeraney That is a valid alternative to deleting the commit done on the wrong branch and will help others in the same situation (good commit done on wrong branch).Ketchup
E
23

Do a git rebase -i FAR_ENOUGH_BACK and drop the line for the commit you don't want.

Ergo answered 7/7, 2010 at 17:55 Comment(1)
If you end up removing all the commits, you can add "noop" as the action, or rebase takes no action. This is my preferred version, because it's very clear what you are changing.Loeb
B
8

If you want to move that commit to another branch, get the SHA of the commit in question

git rev-parse HEAD

Then switch the current branch

git checkout other-branch

And cherry-pick the commit to other-branch

git cherry-pick <sha-of-the-commit>
Berkow answered 7/7, 2010 at 17:55 Comment(1)
From my experience, this does not undo the commit from the original branch, thus necessitating the git reset --hard HEAD~1 afterwards. I think using reset --soft then switching branches and committing again would have saved extra work. Then again I was using SourceTree to do most of my basic stuff, only command line-ing it with this after my error.Meares
T
8

Following command worked for me, all the local committed changes are dropped & local is reset to the same as remote origin/master branch.

git reset --hard origin

Tarbes answered 6/5, 2020 at 12:6 Comment(2)
This is a copy of https://mcmap.net/q/14345/-how-do-i-delete-unpushed-git-commitsNecessitous
I did not notice that response, I tried that command & it worked for me, I posted response accordingly.Tarbes
S
3

For your reference, I believe you can "hard cut" commits out of your current branch not only with git reset --hard, but also with the following command:

git checkout -B <branch-name> <SHA>

In fact, if you don't care about checking out, you can set the branch to whatever you want with:

git branch -f <branch-name> <SHA>

This would be a programmatic way to remove commits from a branch, for instance, in order to copy new commits to it (using rebase).

Suppose you have a branch that is disconnected from master because you have taken sources from some other location and dumped it into the branch.

You now have a branch in which you have applied changes, let's call it "topic".

You will now create a duplicate of your topic branch and then rebase it onto the source code dump that is sitting in branch "dump":

git branch topic_duplicate topic
git rebase --onto dump master topic_duplicate

Now your changes are reapplied in branch topic_duplicate based on the starting point of "dump" but only the commits that have happened since "master". So your changes since master are now reapplied on top of "dump" but the result ends up in "topic_duplicate".

You could then replace "dump" with "topic_duplicate" by doing:

git branch -f dump topic_duplicate
git branch -D topic_duplicate

Or with

git branch -M topic_duplicate dump

Or just by discarding the dump

git branch -D dump

Perhaps you could also just cherry-pick after clearing the current "topic_duplicate".

What I am trying to say is that if you want to update the current "duplicate" branch based off of a different ancestor you must first delete the previously "cherrypicked" commits by doing a git reset --hard <last-commit-to-retain> or git branch -f topic_duplicate <last-commit-to-retain> and then copying the other commits over (from the main topic branch) by either rebasing or cherry-picking.

Rebasing only works on a branch that already has the commits, so you need to duplicate your topic branch each time you want to do that.

Cherrypicking is much easier:

git cherry-pick master..topic

So the entire sequence will come down to:

git reset --hard <latest-commit-to-keep>
git cherry-pick master..topic

When your topic-duplicate branch has been checked out. That would remove previously-cherry-picked commits from the current duplicate, and just re-apply all of the changes happening in "topic" on top of your current "dump" (different ancestor). It seems a reasonably convenient way to base your development on the "real" upstream master while using a different "downstream" master to check whether your local changes also still apply to that. Alternatively you could just generate a diff and then apply it outside of any Git source tree. But in this way you can keep an up-to-date modified (patched) version that is based on your distribution's version while your actual development is against the real upstream master.

So just to demonstrate:

  • reset will make your branch point to a different commit (--hard also checks out the previous commit, --soft keeps added files in the index (that would be committed if you commit again) and the default (--mixed) will not check out the previous commit (wiping your local changes) but it will clear the index (nothing has been added for commit yet)
  • you can just force a branch to point to a different commit
  • you can do so while immediately checking out that commit as well
  • rebasing works on commits present in your current branch
  • cherry-picking means to copy over from a different branch

Hope this helps someone. I was meaning to rewrite this, but I cannot manage now. Regards.

Semple answered 28/7, 2016 at 16:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.