How to undo “git push –mirror”?

On a git/github project I am working on a branch. Upon a push, it said the following:

git push
To git@github.com:...
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:...'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again.  See the 'Note about
fast-forwards' section of 'git push --help' for details.

I tried to fix this problem and upon Googleing I came up with this line:

  • git alias command is not working can any one describe me syntax of git alias command
  • github linking with other repos
  • How do you clone a Git repository into a specific folder?
  • keep git files in another folder
  • git-p4 submit fails with patch does not apply
  • GitPython tags sorted
  • git push --mirror
    

    I issued the following command and now it seems that I have deleted a lot of branches from the server.

    Total 0 (delta 0), reused 0 (delta 0)
    To git@github.com:...
     - [deleted]         develop
     + 797beee...bafbc50 master -> master (forced update)
     - [deleted]         milestone
     - [deleted]         robot
     - [deleted]         strategy
     * [new branch]      origin/HEAD -> origin/HEAD
     * [new branch]      origin/develop -> origin/develop
     * [new branch]      origin/master -> origin/master
     * [new branch]      origin/milestone -> origin/milestone
     * [new branch]      origin/robot -> origin/robot
     * [new branch]      origin/robot_simulator -> origin/robot_simulator
     * [new branch]      origin/strategy -> origin/strategy
     * [new branch]      origin/vision -> origin/vision
    

    Can you tell me what has happened and how can I undo the change I made? (in case I deleted those branches)

  • How to get the current branch name in Git?
  • git - update fork's master & rebase my branch onto it?
  • gitignore ignore files within a folder that has whitespace in the middle
  • What does peel mean in Git?
  • Git - Automatically track all files in a directory
  • Non interactive GIT usage
  • 2 Solutions collect form web for “How to undo “git push –mirror”?”

    You pushed to the default push target, git@github.com. This means, that git@github.com was a remote in you source repo.

    That implies, that the refs deleted from the server would still be in the remote locally after the push. Do not update the remotes (!).

    Verify this by doing

    git branch -a
    

    on the side you pushed from (local).

    It will probably show the refs that were deleted from the remote server.

    [to be continued]

    You could do something like:

    for-each-ref refs/remotes/origin | while read sha type name
    do 
        git branch "rescue_$(basename "$name")" "$sha"
    done
    

    to recover the branches locally. They will be named prefixed with rescue_ just as a precaution (in case you get funny or conflicting ref names).

    Replace origin with the name of your remote


    Test script

    In case you want to test the procedure in a controlled environment, here is my approach condensed to minimum steps (execute in an empty dir, e.g. /tmp/work)

    git init A; (cd A; touch test; git add test; git commit -m initial; git branch test1; git branch test2; git branch test3)
    git clone A B
    (cd B; git push --mirror origin; git branch -a)
    cd A
    git for-each-ref refs/remotes/origin | while read sha type name; do git branch "rescue_$(basename "$name")" "$sha"; done
    git branch -a
    

    Note how in this version, I cd into A – which would be your github repo. You could git clone --mirror git@github.com:... local_rescue in order to get a suitable local version of that.

    I recommend you play around getting to terms with the procedure before trying it out. It never hurts to backup your repositories along the way.

    You were in a situation like this:

    - x - A - B - C (origin/master)
       \
        D - E - F (master)
    

    You wanted to do one of two things, both of which are described in the documentation that Git suggested you read:

    • Pull, then push, giving you this:

      - x - A - B - C
         \           \
          D - E - F - M (master, origin/master)
      
    • Force push (git push --force), giving you this:

      - x - D - E - F (master, origin/master)
      

    Instead, with git push --mirror you basically did the equivalent of force-pushing everything, making the remote repository into a mirror of your local one. This means, just like it reported, deleting everything on the remote that wasn’t in your repository.

    Edit: sehe’s answer describes how to recover. If you have run git remote update, which would have deleted the remote branches it uses to recover from, then the following could be useful. Otherwise, you’re all set.

    Your best bet is to find someone else who has cloned from the remote repository (or if you’re lucky, a separate clone that you’d made), tell them not to pull/fetch/remote update, and follow sehe’s instructions from that repo.

    Failing that, recovering is going to be really tricky. If you’ve interacted with any of the remote branches recently, it’s possible there will be traces in HEAD‘s reflog:

    git reflog show
    

    Otherwise, if the deleted refs refer to commits which are ancestors of any remaining branches, you can maybe recreate them quickly. If they refer to things which aren’t ancestors of remaining branches, you can find dangling commits:

    git fsck
    

    and perhaps figure out which ones had branches pointed to them.

    Git Baby is a git and github fan, let's start git clone.