62

Let's say I make a mistake in my first push to a remote Git repository. Can I somehow revert this so that the repository is back to it's initial state? I don't have access to the remote machine, so deleting .git directory is not possible.

The problem, as far as I can see is that you can't "unset" the head.

This is what I (or actually a colleague who asked about this) did (I do a local "remote" repo here so anyone can test this):

mkdir git-remote
cd git-remote
git init --bare
cd ..
mkdir git-local
cd git-local
git clone ../git-remote .
touch a
git add a
git commit -m "initial"
git push origin master

And at this point he realised he pushed the wrong stuff to the remote repository.

The only idea I had is the delete everything from his repo && git rm && git push which would still leave the faulty commit there, but the files wouldn't bother a second push.

Makis
  • 12,468
  • 10
  • 62
  • 71
  • http://stackoverflow.com/questions/588414/git-rolling-back-a-remote-repository – Christian Feb 07 '11 at 14:06
  • Looks like that is a case where you still are left with at least one commit. I don't want to have a single commit there. – Makis Feb 07 '11 at 14:09

6 Answers6

93

I think you may have an XY problem. You don't actually need to get the remote repository back into its original state in order to start over; you simply need to start over locally, then force-push that to the remote.

# create a new repository that has the initial commit that you want
mkdir foo; cd foo; git init; ...; git commit

# set up a remote
git remote add origin <url-of-remote>
git branch --set-upstream master origin/master

# push your new history
git push -f

# delete obsolete remote branches
git push origin :deprecated-branch

The remote repository never returns to a no-commits state, but it ends up where you want it, and that's all that matters!

(Under the hood, the old commits are actually still in the remote repository, but they're left dangling, with no refs pointing to them. They'll be automatically removed when git gc --auto is triggered by a push at some point.)

If you really, really want to empty it for some reason, you can set receive.denyDeleteCurrent in the remote repository, and push-delete all branches, including the current one. I don't see why you actually need to, though!

Cascabel
  • 479,068
  • 72
  • 370
  • 318
  • 2
    @John: `-f` means `--force`. It's required for non-fast-forward pushes (pushing in branches which don't have the previous position of the branch as an ancestor). – Cascabel Feb 07 '11 at 20:09
  • 11
    Since `--set-upstream` is deprecated, `git branch --set-upstream-to=origin/master master` does the job now (setting up the remote) – Dominikus K. Mar 08 '17 at 23:24
  • @Cascabel how would `git gc --auto` be triggered on remote, like you stated in your answer? Running this locally and pushing is sufficient, or there is something more to be done? – Sekhemty Jan 13 '20 at 21:11
9

Below steps will do it easily, Be careful to take master backup in case needed.

mkdir  reset
cd reset
 git init
 touch README.md
 git add .
 git commit -m 'Initial commit'
 git remote add origin git@github.com:XXX/xxx.git
 git push --force --set-upstream origin master
3

When you say "first push" do you mean the very first push to the branch ever? As in there was no code in it at all before you pushed to it. If that's the case…

If you wanted to push a local branch foo to a remote branch for the first time, you would do this:

git push origin foo:foo

In order to delete remote branch foo, you tell git to push "nothing" to it:

git push origin :foo

Now you can start over with it however you like.

To be honest I'm not sure what actually remains physically on the server -- but in terms of completely resetting branch history, this will work.

(fwiw, I think this interface is pretty ridiculous)

John Bachir
  • 22,495
  • 29
  • 154
  • 227
  • How do you do that to the master branch when it's the only branch there? I added the workflow to my question above. – Makis Feb 07 '11 at 16:17
  • 2
    `git push origin :master` -- because it's the only branch and the one you have checked out, this will generate some errors, which explain how to get around the problem. (again -- this will delete _everything_ in that remote branch!) – John Bachir Feb 07 '11 at 16:39
  • (one easy workaround is `git checkout -b master_tmp; git push origin :master`) – John Bachir Feb 07 '11 at 16:41
  • What exactly do you think is ridiculous? – Cascabel Feb 07 '11 at 17:30
  • 1
    that to delete a remote branch, you "push emptiness to it" 1. is unintuitive. that grammar could just as well mean "push no changes". 2. or really it should be wrong, because deleting a remote branch is a dangerous and special case of pushing. at the very least, `git push origin :foo` should require a `--force` flag. – John Bachir Feb 07 '11 at 18:27
  • Maybe it should require a force flag, yes. But it's completely intuitive to me. Within the idea of a refspec being `:`, it's possibly the only syntax that makes sense. (And why would it every mean "push no changes"? If I say `git push :foo`, clearly I mean to do something with that branch. If I wanted to do nothing, *I'd do nothing*.) – Cascabel Feb 07 '11 at 20:13
  • I've been using git for 2 years every hour of every day and I don't know what "refspec" means… – John Bachir Feb 07 '11 at 21:17
  • (which implies that I don't need to know… which means that if the intuitiveness of the command depends on knowing that… FAIL :-) ) – John Bachir Feb 07 '11 at 21:18
2

Best way to empty the GitHub repository.

Step 1: Create new branch. git checkout -b master1

Step 2: Add your data into its.

git add .

git commit -m "Initial commit"

git push origin master1

Step 3: Now remove old master branch.

git push origin --delete <your_branch>

Mayank Dudakiya
  • 3,635
  • 35
  • 35
1

what I did is:

  1. make neccessary backup of code
  2. delete this repo completely
  3. recreate a repo with the same name

:tada:

Elon Bezos
  • 69
  • 1
  • 6
-4

You can git revert commits, e.g. git revert HEAD.

Keep in mind that the content you committed will reside in the .git directory. (You can't do anything about that)

It's impossible to actually delete a commit from the history without having access to the .git directory.

deleted77
  • 147
  • 1
  • 5
  • 1
    @Makis: This answer is incorrect. You can delete branches on the remote, and force the master branch back to its very first commit. It's true that you can't leave it without any commits at all, *but you can replace the root commit.* The original commits will be left dangling, and eventually cleaned up by `git gc --auto`, which runs automatically now and then. – Cascabel Feb 07 '11 at 17:00
  • Jonas, git commands (including pushing) work by accessing and possibly modifying the contents of the .git directory. You *do* have access to the remote's .git directory through `git push`. It's indirect and incomplete, but it is also sufficient for this task. – Cascabel Feb 07 '11 at 17:11