Rolling back local and remote git repository by 1 commit
GitGit Problem Overview
I've read the similar posts on this topic, and can't for the life of me figure out how to do this properly.
I checked in about 1000 files that I don't want, and I'd rather not have to go through 1by1 and remove them all from the repo.
- I have a remote
master
Branch. - I have the local
master
Branch.
They are both at the same revision.
I want to rollback my remote by 1 commit.
Say my history on master
is A--B--C--D--E
.
I want to rollback my local to D
.
Then push it to remote so my current hash will be D both remote and local.
I'm having issues doing this.
I'm using Git Tower but am comfortable with the command line. Any help?
UPDATE: Great comments below. Using a reset seems to be partially discouraged especially if the repository is shared with other users. What's the best way to undo the previous commit's changes without using a hard reset? Is there a way?
Git Solutions
Solution 1 - Git
If nobody has pulled your remote repo yet, you can change your branch HEAD and force push it to said remote repo:
git reset --hard HEAD^
git push -f
(or, if you have direct access to the remote repo, you can change its HEAD reference even though it is a bare repo)
Note, as commented by alien-technology in the comments below, on Windows (CMD session), you would need ^^
:
git reset --hard HEAD^^
git push -f
And? as noted in the comments by Jon Schneider:
> If the command with "HEAD^
" results in error no matches found: HEAD^
, see "git show HEAD^
doesn't seem to be working. Is this normal?"
Update since 2011:
Using git push --force-with-lease
(that I present here, introduced in 2013 with Git 1.8.5) is safer.
See Schwern's answer for illustration.
> What if somebody has already pulled the repo? What would I do then?
Then I would suggest something that doesn't rewrite the history:
-
git revert
locally your last commit (creating a new commit that reverses what the previous commit did) -
push the 'revert' generated by
git revert
.
Solution 2 - Git
Set the local branch one revision back (HEAD^
means one revision back):
git reset --hard HEAD^
Push the changes to origin:
git push --force
You will have to force pushing because otherwise git would recognize that you're behind origin
by one commit and nothing will change.
Doing it with --force
tells git to overwrite HEAD
in the remote repo without respecting any advances there.
Solution 3 - Git
If you want revert last commit listen:
Step 1:
Check your local commits with messages
$ git log
Step 2:
Remove last commit without resetting the changes from local branch (or master)
$ git reset HEAD^
OR if you don't want last commit files and updates listens
$ git reset HEAD^ --hard
Step 3:
We can update the files and codes and again need to push with force it will delete previous commit. It will keep new commit.
$ git push origin branch -f
That's it!
Solution 4 - Git
By entering bellow command you can see your git commit history -
$ git log
Let's say your history on that particular branch is like - commit_A, commit_B, commit_C, commit_D. Where, commit_D is the last commit and this is where HEAD remains. Now, to remove your last commit from local and remote, you need to do the following :
Step 1: Remove last commit locally by -
$ git reset --hard HEAD~
This will change your commit HEAD to commit_C
Step 2: Push your change for new HEAD commit to remote
$ git push origin +HEAD
This command will delete the last commit from remote.
P.S. this command is tested on Mac OSX and should work on other operating systems as well (not claiming about other OS though)
Solution 5 - Git
Here's an updated version of the procedure which is safer.
git reset --hard HEAD^
git push --force-with-lease
git push -f
will indiscriminately replace the remote repository with your own changes. If someone else has pushed changes they will be lost. git push --force-with-lease
will only push your rebase if the repository is as you expect. If someone else has already pushed your push will fail.
See –force considered harmful; understanding git’s –force-with-lease.
I recommend aliasing this as repush = push --force-with-lease
.
> What if somebody has already pulled the repo? What would I do then?
Tell them to git pull --rebase=merges
. Instead of a git fetch origin
and git merge origin/master
it will git fetch origin
and git rebase -r origin/master
. This will rewrite any of their local changes to master
on top of the new rebased origin/master
. -r
will preserve any merges they may have made.
I recommend making this the default behavior for pulling. It is safe, will handle other's rebasing, and results in less unnecessary merges.
[pull]
rebase = merges
Solution 6 - Git
For Windows Machines, use:
git reset HEAD~1 #Remove Commit Locally
Solution 7 - Git
**Answering very shortly about revert and reset **
There are many way you can do this. Based on your requirement choose anything from below.
1. By REVERTing commit:
If you want to REVERT all the changes from you last COMMIT that means If you ADD something in your file that will be REMOVED after revert has been done. If you REMOVE something in your file the revert process will ADD those file.
You can REVERT the very last COMMIT. Like:
1.git revert HEAD^
2.git push origin <Branch-Name>
Or you can revert to any previous commit using the hash of that commit.Like:
1.git revert <HASH>
OR git revert -m 1 <HASH> if the commit is a merge commit
2.git push origin <Branch-Name>
2. By RESETing previous Head
If you want to just point to any previous commit use reset; it points your local environment back to a previous commit. You can reset your head to previous commit or reset your head to previous any commit.
Reset to very last commit.
1.git reset HEAD^
2.git push -f origin <Branch-name>
Reset to any previous commit:
1.git reset <HASH>
2.git push -f origin <Branch-name>
Trade of between REVERT & RESET:
-
Why would you choose to do a revert over a reset operation? If you have already pushed your chain of commits to the remote repository (where others may have pulled your code and started working with it), a revert is a nicer way to cancel out changes for them. This is because the Git workflow works well for picking up additional commits at the end of a branch, but it can be challenging if a set of commits is no longer seen in the chain when someone resets the branch pointer back.
-
And resetting a branch can be destroying what you have done till now.Because when you reset a commit, GIT will delete all the commits that have done after this commit.One silly mistake can destroy all your hard work and it doesn't keep any history what you are resetting. On the other hand reverting a commit is better option in this scenario. When you revert a commit, GIT creates a new commit with the completely opposite changes of the commit you are willing to revert.And it points to the end of that branch. So it won't mess up anything on our silly mistake.
Solution 8 - Git
I solved problem like yours by this commands:
git reset --hard HEAD^
git push -f <remote> <local branch>:<remote branch>
Solution 9 - Git
You can also do this:
git reset --hard <commit-hash>
git push -f origin master
and have everyone else who got the latest bad commits reset:
git reset --hard origin/master
Solution 10 - Git
If you have direct access to the remote repo, you could always use:
git reset --soft HEAD^
This works since there is no attempt to modify the non-existent working directory. For more details please see the original answer:
Solution 11 - Git
I just wanted to remove last commit from remote and clear commit history also. The following worked like a charm
git reset --hard HEAD^
git push -f
Solution 12 - Git
The way to reset the head and do the revert to the previous commit is through
$ git reset HEAD^ --hard
$ git push <branchname> -f
But sometimes it might not be accepted in the remote branch:
To ssh:<git repo>
! [rejected] develop -> develop (non-fast-forward)
error: failed to push some refs to 'ssh:<git repo>'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
then the other way to do is
git revert HEAD
git push <remote branch>
This works fine.
NOTE: remember if the git push -f <force>
failed and then you try to revert. Do a git pull
before, so that remote and local are in sync and then try git revert
.
Check with git log
to make sure the remote and local are at same point of commit with same SHA1..
git revert
A --> B --> C -->D
A--> B --> C --> D --> ^D(taking out the changes and committing reverted diffs)
Solution 13 - Git
on local master
git reflog
-- this will list all last commit
e.g Head@{0} -- wrong push
Head@{1} -- correct push
git checkout Head@{1} .
-- this will reset your last modified files
git status
git commit -m "reverted to last best"
git push origin/master
No need to worry if other has pulled or not.
Done!
Solution 14 - Git
If you only want to remove the last commit from the remote repository without messing up with your local repository, here's a one-liner:
git push origin +origin/master~:master
This uses the following syntax:
git push <remote> <refspec>
Here, <remote>
is origin
, and <refspec>
has the following structure:
+origin/master~:master
Details can be found in git-push(1)
. The preceding +
means "force push this ref", and the other part means "from origin/master~
to master
(of remote origin
)". It isn't hard to know that origin/master~
is the last commit before origin/master
, right?
Solution 15 - Git
for me works this two commands:
git checkout commit_id
git push origin +name_of_branch