157

I have 2 commits that I did not push:

$ git status
# On branch master
# Your branch is ahead of 'faves/master' by 2 commits.

How can I roll back my first one (the oldest one), but keep the second one?

 $ git log
commit 3368e1c5b8a47135a34169c885e8dd5ba01af5bb
...

commit baf8d5e7da9e41fcd37d63ae9483ee0b10bfac8e
...

From here:

http://friendfeed.com/harijay/742631ff/git-question-how-do-i-rollback-commit-just-want

Do I just need to do:

git reset --hard baf8d5e7da9e41fcd37d63ae9483ee0b10bfac8e

That is?

2
  • 4
    This question appears to be off-topic because it is about a programming tool. It belongs on Stack Overflow. Commented Jul 12, 2014 at 11:52
  • @PeterMortensen Agreed. This is of scope for SuperUser Commented Aug 17, 2018 at 17:00

10 Answers 10

109

The safest and probably cleanest way to go is to rebase interactively.

git rebase -i HEAD^^

Or,

git rebase -i baf8d5e7da9e41fcd37d63ae9483ee0b10bfac8e^

From there you can squash commits, which puts one or more commits together into the previous commit. To completely delete a commit from the history, delete the line from the list.

You can revert a commit with git revert but its going to add more commit messages to the history, which may be undesirable. Use the -n parameter to tell Git not to commit the revert right away. You can rebase interactively and squash those on up to a previous commmit to keep things clean.

If the two commits you're working with here affect the same file(s), you may see a merge conflict.

Resetting the repository with git reset --hard should be done with care, as it cannot be undone.

Rewriting history should be done with care.

6
  • How can I delete a commit in during 'git rebase'? There are only 3 commands: pick, edit, squash. There is no delete AFAIK.
    – n179911
    Commented Sep 4, 2009 at 4:22
  • 8
    delete the line from the list entirely, and it deletes that commit
    – jtimberman
    Commented Sep 4, 2009 at 5:10
  • when I wanted to revert the change I wanted to leave no trace of it. If you also want to leave no trace of your revert this is the best way to do it. Commented Apr 14, 2011 at 1:52
  • 1
    "safest and probably cleanest way to go is to rebase interactively" Maybe not if you don't use vim. I got lucky and figured my way out of that mess. Still upvoting because I should learn vim :-)
    – isimmons
    Commented Dec 13, 2013 at 3:42
  • I would suggest use rebase as less as possible. If you work with others then just make revert.
    – magnump0
    Commented Dec 31, 2013 at 12:08
68

This if from http://nakkaya.com/2009/09/24/git-delete-last-commit/ and it worked for me

Git Delete Last Commit

Once in a while late at night when I ran out of coffee, I commit stuff that I shouldn't have. Then I spend the next 10 - 15 minutes googling how to remove the last commit I made. So after third time I wanted to make a record of it so I can refer to it later.

If you have committed junk but not pushed,

git reset --hard HEAD~1

HEAD~1 is a shorthand for the commit before head. Alternatively you can refer to the SHA-1 of the hash you want to reset to. Note that when using --hard any changes to tracked files in the working tree since the commit before head are lost.

If you don't want to wipe out the work you have done, you can use --soft option that will delete the commit but it will leave all your changed files "Changes to be committed", as git status would put it.

Now if you already pushed and someone pulled which is usually my case, you can't use git reset. You can however do a git revert,

git revert HEAD

This will create a new commit that reverses everything introduced by the accidental commit.

1
  • 2
    With the --soft option, it's perfect for where you rename a file and accidentally "git commit -a" rather than using "git add" first. Commented Jul 18, 2013 at 10:45
8

Nope. git-reset --hard will bring you back in history. What you're looking for is git revert, which will undo any commit.

1
  • 6
    Well, this works but it also pollutes you commit log. If these commits were not pushed/pulled already it's better to clean them up with an interactive rebase. The ability to change history is one of the main advantages of git over other version control systems.
    – knweiss
    Commented Sep 3, 2009 at 21:49
6

I just done this:

git rebase -i HEAD^^

I screwed it up so I did

git rebase --abort

Then did it again. Then I had to push like this:

git push origin master -f

And it destroyed the commits newer than the commit I had rolled back to. Worked great.

5

No, git reset --hard baf8d5e will delete the 3368e1c commit and HEAD will be at baf8d5e afterwards.

If you want to keep the 3368e1c commit and delete the bad8d5e commit the easiest solution is to do a "git rebase -i HEAD~2" (i.e. interactive rebase of the last two commits). This command will launch your commit message editor and you'll see one line for each of the last two commits. There you just delete the bad8d5e commit line and save. git will then rewrite your history and the 2nd commit will be gone.

There are other useful commands you can use in the commit message editor like squash, edit, etc. Interactive rebase is VERY powerful!

Do not do this if somebody already saw these commits (push or pull from your repository)!

4

In reference to jtimberman's comment about git reset --hard being undoable, that's not entirely true. See here: https://stackoverflow.com/questions/5473/undoing-a-git-reset-hard-head1

0
1
git reset --hard {ref}

is the only way to undo a commit if there is only one other commit in the repo (e.g. initial commit and 1 more). The rest of the ways (revert, rebase) refuse to work, at least as of git 1.7.5.1.

If you follow the git reset with a git gc then git will actually delete the old commit data from the repo completely.

1
git checkout <treeish> -- /path/to/dir

That will bring back the directory from the given “treeish” for the /path/to/dir

0

I got this to work by manually editing the hash codes of the last commits from HEAD files inside the repository folder:

"centralRepository\refs\heads\master"
"centralRepository\refs\heads\branch2"

Before that, I was never able to push to origin the UNMERGE operations I did locally. It kept saying it "failed to push some refs" to Central Repository.

0

Or just fetch the remote branch on pull request:

git fetch origin/<name of branch on pull request> -b <name of branch on pull request (if making changes to same pull request)/name of another branch (e.g.: main)>

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .