Search code examples
gitversion-controlatlassian-sourcetree

Reverting commits on remote branch


I made two commits to my Master branch that were then pushed to the remote branch.

I've now decided to go back to my original code before those two commits and so selected my original commit with Reset Master to Commit (using SourceTree). I then made a few changes and committed these.

The problem is when I try to push to the remote it tells me I need to fetch first. I could get around this with a Force Push but I'd like to keep my commit history.

Is this possible without making a new branch?


Solution

  • TL;DR Use git revert to undo the commits you want to remove in a way that documents the fact you're undoing them, then merge or rebase.

    Details

    In order to keep your history as easy to understand as possible in the future, I would first revert the two commits you don't want to keep, on the master branch.

    Since you have commits on your local master branch you want to keep, I'm going to temporarily create another branch off of origin/master to make things simplest.

    git checkout origin/master
    git checkout -b dev.about-to-revert
    

    Now, create "revert" commits to undo the two commits you don't want to keep:

    git revert <commit to revert>
    git revert <commit to revert>
    

    From the git revert manual: "Given one or more existing commits, revert the changes that the related patches introduce, and record some new commits that record them."

    So now branch dev.about-to-revert has the same code as origin/master before the two commits, and you can either rebase or merge in your new work.

    Rebase:

    git checkout master
    git rebase dev.about-to-revert
    

    Or merge

    git checkout master
    git merge dev.about-to-revert
    

    Or merge the other way if you prefer having the parents of the merge in the other direction:

    git merge master
    git checkout master
    git merge dev.about-to-revert
    

    And now you're done with dev.about-to-revert so you can get rid of it:

    git branch -d dev.about-to-revert
    

    PS: you asked "Is this possible without creating a new branch". I assume you don't want to push a new branch on the remote, but that it's still OK to create one temporarily in your sandbox. There are ways to do the same operations I show here without a new branch, doing the reverts on a detached HEAD, but it's simpler as shown here.