Delete last commit in bitbucket
Here is a simple approach in up to 4 steps:
0 - Advise the team you are going to fix the repository
Connect with the team and let them know of the upcoming changes.
1 - Remove the last commit
Assuming your target branch is master
:
$ git checkout master # move to the target branch
$ git reset --hard HEAD^ # remove the last commit
$ git push -f # push to fix the remote
At this point you are done if you are working alone.
2 - Fix your teammate's local repositories
On your teammate's:
$ git checkout master # move to the target branch
$ git fetch # update the local references but do not merge
$ git reset --hard origin/master # match the newly fetched remote state
If your teammate had no new commits, you are done at this point and you should be in sync.
3 - Bringing back lost commits
Let's say a teammate had a new and unpublished commit that were lost in this process.
$ git reflog # find the new commit hash
$ git cherry-pick <commit_hash>
Do this for as many commits as necessary.
I have successfully used this approach many times. It requires a team effort to make sure everything is synchronized.
If you are not working with others (or are happy to cause them significant annoyance), then it is possible to remove commits from bitbucket branches.
If you're trying to change a non-master branch:
git reset HEAD^ # remove the last commit from the branch history
git push origin :branch_name # delete the branch from bitbucket
git push origin branch_name # push the branch back up again, without the last commit
if you're trying to change the master branch
In git generally, the master branch is not special - it's just a convention. However, bitbucket and github and similar sites usually require there to be a main branch (presumably because it's easier than writing more code to handle the event that a repository has no branches - not sure). So you need to create a new branch, and make that the main branch:
# on master:
git checkout -b master_temp
git reset HEAD^ # undo the bad commit on master_temp
git push origin master_temp # push the new master to Bitbucket
On Bitbucket, go to the repository settings, and change the "Main branch" to master_temp
(on Github, change the "Default branch").
git push origin :master # delete the original master branch from Bitbucket
git checkout master
git reset master_temp # reset master to master_temp (removing the bad commit)
git push origin master # re-upload master to bitbucket
Now go to Bitbucket, and you should see the history that you want. You can now go to the settings page and change the Main branch back to master
.
This process will also work with any other history changes (e.g. git filter-branch
). You just have to make sure to reset to appropriate commits, before the new history split off from the old.
edit: apparently you don't need to go to all this hassle on github, as you can force-push a reset branch.
Dealing with annoyed collaborators
Next time anyone tries to pull from your repository, (if they've already pulled the bad commit), the pull will fail. They will manually have to reset to a commit before the changed history, and then pull again.
git reset HEAD^
git pull
If they have pulled the bad commit, and committed on top of it, then they will have to reset, and then git cherry-pick
the good commits that they want to create, effectively re-creating the whole branch without the bad commit.
If they never pulled the bad commit, then this whole process won't affect them, and they can pull as normal.
you can reset to HEAD^
then force push it.
git reset HEAD^
git push -u origin master --force
It will delete your last commit and will reflect on bitbucket as commit deleted but will still remain on their server.
In the first place, if you are working with other people on the same code repository, you should not delete a commit since when you force the update on the repository it will leave the local repositories of your coworkers in an illegal state (e.g. if they made commits after the one you deleted, those commits will be invalid since they were based on a now non-existent commit).
Said that, what you can do is revert the commit. This procedure is done differently (different commands) depending on the CVS you're using:
On git:
git revert <commit>
On mercurial:
hg backout <REV>
EDIT: The revert operation creates a new commit that does the opposite than the reverted commit (e.g. if the original commit added a line, the revert commit deletes that line), effectively removing the changes of the undesired commit without rewriting the repository history.