73

I have a git repository which holds a Drupal site. I spent the last day trying to build a feature using several different modules. I have given up on my current approach and have decided to try a different combination of modules. However, my repository has several commits on the master branch that contain this feature development process (I understand that I did not branch in an effective manner.) I want to get rid of the last three or four commits and set master to that point in my history (I don't want to merge my current work with anything, I just want it to go away.) How do I do this?

4
  • Have you already pushed your changes to the remote? Commented Apr 22, 2014 at 19:00
  • I am not currently using a remote. I will probably set that up in a few days Commented Apr 22, 2014 at 19:42
  • 1
    possible duplicate of Revert to previous Git commit Commented Apr 22, 2014 at 19:46
  • Looks like the same answer. Commented Apr 22, 2014 at 19:54

5 Answers 5

139

In order to do it locally, you can do the following commands to go to master and move it to the old commit.

git checkout master git reset --hard <old_commit_id> 

If you then want to push it to the remote, you need to use the -f option.

git push -f origin master 
Sign up to request clarification or add additional context in comments.

4 Comments

Could I ask for a good place to find a list of options that git uses and their meaning? I don't know what --hard or -f does.
Actually, I just found this documentation link : kernel.org/pub/software/scm/git/docs/git.html
@Mr JF, That is true. One must unprotect to rewrite history. There's no other way.
lots of merit in the backup strategy suggested by william_grisaitis
21

Before pointing main to a previous commit, I recommend backing up your current main:

$ git checkout -b main_backup 

Then you can safely point main some number of commits back, e.g. 3:

$ git reset --hard main~3 

After moving main, see your tree of commits:

$ git log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all 

Now, I would recommend keeping the backup until you're absolutely sure it's unnecessary (for instance, once your new approach is fully implemented), but when you're sure, you can clean up by deleting main_backup:

$ git branch -D main_backup 

Comments

3

Note that at any given time you can change where a branch points to by using git update-ref refs/heads/branch id , but before you do this, you must give a name to the tip of the tree, otherwise your work will unaccessible. So these two commands may do the job

 git update-ref refs/heads/newfeature HEAD git update-ref refs/heads/master XXYYY 

But make sure that you do not have any uncommited changes otherwise all hell will break loose

3 Comments

I had no uncommited changes but got as a result a new state with some changes uncommited which seemed to be operations to undo the work done in the branch I want to back off. -- clear why.
that is the expected behaviour. Those commands do not change your files in any way, they just update the reference between "name of the branch" and "what git thinks should be in the filesystem tree". It is then up to to you to commit, or not, the changes between the current HEAD and your working tree. Otherwise, if you do not wish to add any changes to current HEAD, but start over from it, just "hard reset" the tree
thank you for the important clarifcation.
1

You can always do a git reset <commit>. Perhaps the easiest way to do this is use a graphical frontend, i.e. gitk.

You should perhaps first do a git branch branch-for-failed-experiment so the work on the experiment isn't lost forever.

Be careful, if you published the branch (i.e., if others could have work based on your to-be-deleted commits), they will be left stranded. Make sure they sync up with you.

3 Comments

I don't think I want anyone ever to know how bad I messed that one up :P
It sounds like what I really want to do is make a new commit in which all the mistakes are removes (which would look identical to a commit made 3 or 4 commits ago.) How would I do that?
You can revert the commits. Or you could do something like git diff <old>..<current>, stash the result away in a file, and then git apply -R this to undo all changes, then git commit -a the result. But I'd prefer to create a clean history (even if it is completely fake).
0

With gitk: right click the commit, then select "Reset master branch to here".

You'll be given a choice between soft, mixed, and hard reset. See What's the difference between git reset --mixed, --soft, and --hard? Assuming you've committed everything and want nothing leftover, staged or unstaged, use --hard.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.