ndp
ndp

Reputation: 893

Reset git repository to specific commit from specific branch

I was working on a branch which was in the following state

        A'--B'--C'--D'
       /
A--B--C--D

some very bad things happened and I have to go back to B' both locally and remote so that the remote repository is the following

         A'--B'
        /
 A--B--C--D

For the local repository I did

git reset --hard <sha>

but how can I do that for the remote repository?

I should be able to do something like

git push origin mybranch --reset

but it's not in the man page

I tried creating a commit which would cancel the previous ones but

git add .

reports that there are no changes (expected since I'm exactly after the previous push)

So how can I reset the remote repository?

Upvotes: 3

Views: 929

Answers (2)

Alexander Gladysh
Alexander Gladysh

Reputation: 41383

To override a tracked remote branch with yours, do git push origin --force mybranch. (Or use -f instead of --force, or prefix the branch name with +: git push origin +mybranch.)

Note that you should warn any collaborators that may have changed your branch that it has been changed remotely, so they will not override it back. Because git push on their copies will do fast-forward for remote branch — unless you made at least one new commit to it, and git pull will not update their local version of a branch. Collaborators should do:

git fetch origin
git checkout mybranch
git rebase origin/mybranch

Updated for completeness: As @CodeGnome suggests, to completely remove commits from existence, run git prune --expire now on all Git repos that contained them. Be warned though, that this command will remove all dangling objects from Git, and will prevent recovery of any data that you 'lost' before you run it. It is usually OK, but you need to be warned anyway.

Update: as this page suggests, git prune --expire now will not clean commit from reflogs. See the link for the solution. For a less-invasive solution, try git reflog expire --all mybranch. You have to do this before you run git prune.

Sometimes it is more preferable to explicitly generate an "undo" commit that removes the changes (so old version and the fact of its removal are visible in history). There is a git revert command for it.

Upvotes: 4

Todd A. Jacobs
Todd A. Jacobs

Reputation: 84343

Removing Commit from History

All you really need to do is be on the B' branch, and then go git push --force to overwrite the current commit pointer for that branch. If you don't have your remotes set up as tracking branches, you may need to do git push --force origin <branchname> instead.

C' and D' will remain in the reflog and as objects in the repository until they are eventually pruned, but shouldn't show up as part of any log history unless you start digging into the plumbing.

Removing Dangling Objects from the Repository

If you want C' and D' out of the repository altogether, you can call git prune --expire now in both repositories. That should remove the dangling objects altogether.

Upvotes: 3

Related Questions