This post is about how to undo a change made in git that has been pushed to the remote repository where you want this undo to be reflected should anyone in the future pull from the repository.

First some context

If you use git then it is likely that at some point you will push a change to a repository where you want to revert it back afterwards. It may be you accidentally broken something as part of a merge or stash issue. In our case we ran git add . --all when we had some stashed changes that we didn't want to keep. The result was a load of deletions from a different branch... Oops! For the context of this article, the remote repository we use is Beanstalk.

The Steps

So here is an easy step by step of what I did (and what you could do) to essentially undo the error:

  1. Navigate to the branch in question. In my case this was v2.0.0.
    git checkout v2.0.0

  2. Discover the ID of the commits we want to revert to.
    git log
    This shows you all of the commits made to the current branch. In my case the one I wanted to revert to was fbd7e850, you will need to find what yours is in this list.

  3. Now we want to reset our head pointer to point at this commit
    git reset --hard fbd7e850

  4. Now here is where your remote repository settings are important as they need to enable "fast-forwards". In beanstalk these are the steps:
    1. Log in and select the repository.
    2. Visit the repository's settings.
    3. Scroll to advanced settings and enable "Enable non Fast-Forward pushes"
    4. Save
      Note: I'd turn this off again once you have done the revert so that nobody else can do it by accident.

  5. Now you can run the following command to commit the revert:
    git push origin v2.0.0 --force
    With fast forwards enabled this will set the head of the remote repo to match yours.

  6. Still having problems? You could try sepecifically pushing the commit you want to revert to:
    git push origin fbd7e850:v2.0.0
    Though this shouldn't be neccessary.

  7. Now where it gets a little confusing is that if you log into your remote repository then you may notice the commit you wanted to forget is still on top. On your local machine try adding a file into your brance (in my case v2.0.0) and pushing it with
    git add .
    git commit -m 'some test'
    git push origin v2.0.0
    What you should notice is that your change is actually above this change that you want to forget about. This is a good thing as it means GIT still remembers it and should we have messed up further we could stull revert back to that commit... which is nice.

And there you go, you are now ready to continue on as if the change never happened. You need to be very careful when running reset commands, especially in team working environments as a miss placed reset could confuse people and required later merges if not communicated. Once done I'd recommend adding a comment next to the side-stepped commit that explains its removal from the branch in some way.