Search code examples
gitversion-controlrevert

Need to remove bad commit and preserve local changes in git


We have a problem with our git project:

  • bad changes were pushed to the remote repository
  • one machine has not pull-ed the bad changes, but has uncommitted local changes

We want to get rid of the bad changes from the remote repository, and then push the good changes.

We're not very experienced with git, and are afraid of screwing it up and losing the uncommitted, good changes. We're not sure whether we need to use git revert or git rebase (or something else), and from which computer (i.e. from one that doesn't have the good changes?).


Solution

  • First off: Don't panic

    This is a revision control system. It exists so you can't easily loose information.

    You can always save the work first:

    git checkout -b RESCUE_THIS
    git add .
    git commit -am 'Do not loose this commit!'
    

    and take it from there.

    I suggest:

    1. revert the bad commit

      • git reset HEAD@{1} # if it was the last commit

        you need to work out which changes you DO want to keep and potentially commit them into a new commit. Note use git reflog to find the 'HEAD@{1}part that you want. Take your time as this can be a bit confusing when comparing togit log`

      • git revert bad-commit-id # if it wasn't

        Note locate the revisions to revert with git log. You can revert multiple commits. Revert them in reverse chronological order. Each revert will result in a new commit that 'undoes' the chances from that commit.
        If you find yourself reverting plenty commits, you might want to rebase instead.

    2. force push the fixed branch to the central repo

      • git push -f # perhaps specify branch: origin master or similar
    3. restore any remaining work form the 'good' client, e.g. by

      • git checkout master # switch back from RESCUE_THIS

      • git merge --no-commit --ff RESCUE_THIS

      • git commit -am

      • git push # when you are truly satisfied with the result

    By that time you could opt to delete the RESCUE_THIS branch. Even if you do, it will not actually disappear until the reflog(s) expire.

    Disclaimer: all the above is rife with assumptions about your setup, branch history, workflow, and particular failure scenario. Rest assured, they are educated guesses and most of the time coincide with common practice. Keep your eyes open and think it over for yourself, though. As a last resort, you can take a physical backup of the git repo on the 'good client' for safety