Undo pushed commits

I have a project in a remote repository, synchronized with a local repository (development) and the server one (prod). I've been making some commited changes already pushed to remote and pulled from the server. Now, I want to undo those changes. So I could just git checkout to the commit before the changes and commit the new changes, but I'm guessing that there will be problems to push them again to remote. Any suggestion on how should I proceed?


You can revert individual commits with:

git revert <commit_hash>

This will create a new commit which reverts the changes of the commit you specified. Note that it only reverts that specific commit, and not commits after that. If you want to revert a range of commits, you can do it like this:

git revert <oldest_commit_hash>..<latest_commit_hash>

It reverts the commits between and including the specified commits.

Look at the git-revert man page for more information about the git revert command. Also look at this answer for more information about reverting commits.


A solution that keeps no traces of the "undo".

NOTE: don't do this if someone allready pulled your change (I would use this only on my personal repo)

do:

git reset <previous label or sha1>

this will re-checkout all the updates locally (so git status will list all updated files)

then you "do your work" and re-commit your changes (Note: this step is optional)

git commit -am "blabla"

At this moment your local tree differs from the remote

git push -f <remote-name> <branch-name>

will push and force remote to consider this push and remove the previous one (specifying remote-name and branch-name is not mandatory but is recommended to avoid updating all branches with update flag).

!! watch-out some tags may still be pointing removed commit !! how-to-delete-a-remote-tag


What I do in these cases is:

  • In the server, move the cursor back to the last known good commit:

    git push -f origin <last_known_good_commit>:<branch_name>
    
  • Locally, do the same:

    git reset --hard <last_known_good_commit>
    #         ^^^^^^
    #         optional
    



  • See a full example on a branch my_new_branch that I created for this purpose:

    $ git branch
    my_new_branch
    

    This is the recent history after adding some stuff to myfile.py :

    $ git log
    commit 80143bcaaca77963a47c211a9cbe664d5448d546
    Author: me
    Date:   Wed Mar 23 12:48:03 2016 +0100
    
        Adding new stuff in myfile.py
    
    commit b4zad078237fa48746a4feb6517fa409f6bf238e
    Author: me
    Date:   Tue Mar 18 12:46:59 2016 +0100
    
        Initial commit
    

    I want to get rid of the last commit, which was already pushed, so I run:

    $ git push -f origin b4zad078237fa48746a4feb6517fa409f6bf238e:my_new_branch
    Total 0 (delta 0), reused 0 (delta 0)
    To git@github.com:me/myrepo.git
     + 80143bc...b4zad07 b4zad078237fa48746a4feb6517fa409f6bf238e -> my_new_branch (forced update)
    

    Nice! Now I see the file that was changed on that commit ( myfile.py ) shows in "not staged for commit":

    $ git status
    On branch my_new_branch
    Your branch is up-to-date with 'origin/my_new_branch'.
    
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git checkout -- <file>..." to discard changes in working directory)
    
        modified:   myfile.py
    
    no changes added to commit (use "git add" and/or "git commit -a")
    

    Since I don't want these changes, I just move the cursor back locally as well:

    $ git reset --hard b4zad078237fa48746a4feb6517fa409f6bf238e
    HEAD is now at b4zad07 Initial commit
    

    So now HEAD is in the previous commit, both in local and remote:

    $ git log
    commit b4zad078237fa48746a4feb6517fa409f6bf238e
    Author: me
    Date:   Tue Mar 18 12:46:59 2016 +0100
    
        Initial commit
    
    链接地址: http://www.djcxy.com/p/49278.html

    上一篇: 列出并删除没有分支的Git提交(dangling?)

    下一篇: 撤消推送提交