131

I want to rollback to a previous commit, and then publish that code, then go back to the latest commit.

i.e. so my master is pointing to an older commit version just so I can pulish that version, then I want to go back to the latest commit I was one initially.

How can I do this?

Blankman
  • 259,732
  • 324
  • 769
  • 1,199

8 Answers8

113

If you want to do this and revert the master to the previous commit:

git checkout master~1            # Checkout previous commit on master
git checkout -b new_master       # Create branch for new master
git branch -D master             # Delete old master
git branch -mv new_master master # Make new_master master

Alternatively:

git reset --hard master~1        # Reset current branch to one commit ago on master
Community
  • 1
  • 1
Tyler Brock
  • 29,626
  • 15
  • 79
  • 79
  • 1
    So a year later i'm looking at this and thinking this is an awful way to do it. Oh well at least it's somewhat easy to understand. – Tyler Brock Dec 13 '13 at 01:04
  • 1
    yes this is why I upvoted, easy to understand, maybe you should have presented a link to a better way? – Andrew Atkinson Mar 15 '15 at 19:33
  • 1
    I had to do the same using SourceTree. The process is similar. 1) create new branch for current master state, so you won't lose anything. 2) delete master 3) create new master branch, selecting the desired commit – Danilo Gomes Feb 12 '16 at 10:00
  • 1
    What happens to the commit we "removed" from master after this? – Arthur Colombini Gusmão Jan 06 '18 at 14:54
  • It's still in your reflog. Nothing comitted is ever "removed" this just re-points your HEAD at another commit. – Tyler Brock Jan 23 '18 at 18:37
  • Just followed this advice and erased other uncommited changes that I forgot about. There seems to be no way to recover it :( https://stackoverflow.com/questions/5788037/recover-from-git-reset-hard See safer commands are discussed there. They recommend unlearning `git reset` because it is too dangerous. Of course in some situations this is helpful, but it should be understood that some data might be erased. – Sergey Dovgal Feb 09 '18 at 17:32
  • 1
    This should be avoided if you have a remote repo. It causes some errors if you do, because the address of the first master differs from the new master you created recently. – MAChitgarha Aug 10 '18 at 16:23
102

If you want to avoid force pushing, here's how to revert your repo to an older commit and preserve all intervening work:

git checkout 307a5cd        # check out the commit that you want to reset to 
git checkout -b fixy        # create a branch named fixy to do the work
git merge -s ours master    # merge master's history without changing any files
git checkout master         # switch back to master
git merge fixy              # and merge in the fixed branch
git push                    # done, no need to force push!

Done! Replace 307a5cd with whatever commit you want in your repo.

(I know the first two lines can be combined, but I think that makes it less clear what's going on)

Here it is graphically:

c1 -- c2 -- c3 -- c4 -- c2' -- c5 ...
        \              /
         '------------'

You effectively remove c3 and c4 and set your project back to c2. However, c3 and c4 are still available in your project's history if you ever want to see them again.

bronson
  • 5,612
  • 3
  • 31
  • 18
  • 7
    This worked without a hitch! If you have come down this far and are reading this -- this appears to be the cleanest way to revert master to a deeper commit. – ddisqq Feb 07 '20 at 20:29
  • 5
    I can not find the words to explain how much I love you for this, I am greatful beyond words for getting to fix something that had me bugged for 6h now and caused me so much headache. Thank you sir!!!!!!! – Kostas Tsakalidis May 12 '20 at 15:29
  • 1
    To anyone who is looking for a solid solution! – Neelansh Verma Dec 04 '20 at 15:22
  • 10
    For anyone scratching their head over 'ours' mentioned above. Its a built-in git command.. https://howchoo.com/git/git-merge-conflicts-rebase-ours-theirs – Evolve Jun 23 '21 at 04:26
  • 4
    @Blankman I suggest you make this the accepted answer it covers everything people are needing and it's safe unlike the current top answer. – Evolve Jun 23 '21 at 04:27
  • 2
    This is the answer I was looking for! Dear reader, this is the answer you should try. – Gabriel Arghire Apr 05 '22 at 16:39
  • A slightly safer way is to merge origin/master which is more likely to match the intention, especially if you're used to work (only) with feature branches and your local master may be out-of-date. Of course this requires that you have done git fetch – robinr Jul 05 '22 at 13:53
74

Your question is unclear. I think what you are asking for is this:

git push -f origin $old_commit_id:master

What will this do? It will push the $old_commit_id commit to origin as the new head of origin’s master branch.

If that is what you wanted, you do not need to touch your local master branch at all.

Aristotle Pagaltzis
  • 112,955
  • 23
  • 98
  • 97
51

use git reset --hard <old commit number>

it will reset the HEAD to this old commit.

additionally, you need to use git push -f origin to alter the remote repo too.

KawaiKx
  • 9,558
  • 19
  • 72
  • 111
10

Assuming a commit graph like so:

| (A) ---------> (B) ----------> (C)
|                                 ^
|                              (master)

You want to first checkout master and create a branch that points to where master currently is:

git checkout master
git branch pointer master

Should look like this now:

| (A) ---------> (B) ----------> (C)
|                                 ^
|                       (HEAD, master, pointer)

Now that you're already on master, we'll tell the master branch to move backward one commit:

git reset master~1

Now, master should be moved back one space, but the pointer branch is still on the most recent commit :

| (A) ---------> (B) ----------> (C)
|                 ^               ^
|           (HEAD, master)    (pointer)

At this point, you can push master to a remote, or where ever, then fast forward merge it back up to the pointer branch. You can kill the pointer branch at that point :

git push origin master
git merge --ff-only pointer
git branch -D pointer

Final :

| (A) ---------> (B) ----------> (C)
|                 ^               ^
|         [ origin/master ]    (HEAD, master)
C0M37
  • 574
  • 5
  • 14
  • 1
    If origin/master is at C, `git push origin master` will fail with _the tip of your current branch is behind its remote counterpart_. You should also pass a -f flag. – sassospicco Jun 29 '16 at 21:14
10

You can just git checkout <commit-id>, do whatever you need to do, then git checkout master to get back to the new code.

If you actually need to modify the old code to release it, then you should probably:

git checkout -b my_release <commit-id>
... prepare code for release ...
... release code ...
git checkout master
git merge my_release

Also, I can't recommend git flow enough. It makes all of this quite easy.

jtdubs
  • 13,585
  • 1
  • 17
  • 12
1

To move to a previous version:

git checkout <version hash>

do your work here and commit it with

git commit --amend

To go back to master:

git checkout master

Pablo Fernandez
  • 103,170
  • 56
  • 192
  • 232
0

checkout to your old commit:

git reset --hard <your old commit>

create a new branch:

git checkout -b BugfixingV1 

now merge it with the master branch and keep your changes by conflicts:

git merge -s ours master

Now our new Branch is ready to be our new master branch, so let's switch again to the master branch:

git checkout master

and now we need to merge the new branch into the master!

git merge BugfixingV1 

Finally, we'll push the the changes into the Repository:

git push
mustafa
  • 1
  • 1
  • 1