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?
13 Answers
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 that come 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.
To know the hash of the commit(s) you can use git log
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 [email protected]: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
You can REVERT (or you can also call it DELETE) the Git Commit BOTH Locally and Remotely if you follow the steps as given below via git command line.
Run the following command to see the commit id that you want to revert
git log --oneline --decorate --graph
You will get like a following screenshot
If you also check remote (via Web Interface) then you can see that this would be same as shown below
As per screenshot currently you are on commit id e110322 however you want to revert back to 030bbf6 BOTH LOCALLY and REMOTELY.
Perform the following steps to DELETE/REVERT Commits Locally+Remotely
First Locally Reverting to commit id 030bbf6
git reset --hard 030bbf6
followed by
git clean -f -d
These two commands clean force reset to commit stage 030bbf6 as shown below in snapshot
now if you run git status then you'll see that you are TWO Commits BEHIND from the remote branch as shown below
Run following to update your indexes (if there are any updates). It is recommended that you ask all developers not to accept any pull requests on main remote branch.
git fetch --all
Once you are done with it then you are required to Push this commit forcefully by using + symbol in-front of branch as shown below. I have used here as master branch, you can replace it with any
git push -u origin +master
now if you see the web interface of remote then commit there should be reverted as well.
git revert HEAD -m 1
In the above code line. "Last argument represents"
1 - reverts one commits.
2 - reverts last two commits.
n - reverts last n commits.
You need to push after this command to take the effect on remote. You have other options like specifying the range of commits to revert. This is one of the option.
Later use git commit -am "COMMIT_MESSAGE"
then git push
or git push -f
The reset hard worked for me: Thanks @Mo D Genensis and @vibs2006
git reset --hard 'your last working commit hash'
git clean -f -d
git push -f
Here is my way:
Let's say the branch name is develop
.
# Checkout a new temp branch based on one history commit
git checkout <last_known_good_commit_hash>
# Delete the original develop branch
git branch -D develop
# Create a new develop branch based on the temp branch
git checkout -b develop
# Force update this new branch
git push -f origin develop
Another way to do this without revert (traces of undo):
Don't do it if someone else has pushed other commits
Create a backup of your branch, being in your branch my-branch
. So in case something goes wrong, you can restart the process without losing any work done.
git checkout -b my-branch-temp
Go back to your branch.
git checkout my-branch
Reset, to discard your last commit (to undo it):
git reset --hard HEAD^
Remove the branch on remote (ex. origin
remote).
git push origin :my-branch
Repush your branch (without the unwanted commit) to the remote.
git push origin my-branch
Done!
I hope that helps! ;)
To do it cleanly:
git rebase -i <hash of last good commit, 9 chars is enough>
Now you will get a list of the commits from the last good commit to the HEAD
with options what to do with each commit. DROP
will throw away that commit. Save the file.
Now to fix the upstream do :
git push --force-with-lease
(With lease so you don't accidentally cause problems for someone else working on your pushed update)
This keeps the log clean by removing the wrong commit instead of introducing new commits fixing earlier erroneous commits.