15

I just ran git push -f by mistake, thus overwriting a remote branch.

Original:

(remote origin:)
    branch master -> commit aaaaaaa
    branch foo    -> commit bbbbbbb

(local)
    branch master -> commit ccccccc
    branch foo    -> commit ddddddd

After git push -f:

(remote origin:)
    branch master -> commit ccccccc
    branch foo    -> commit ddddddd

In my local repository, I'm working on the master branch, so I can restore the branch master to commit aaaaaaa, because I can get commit aaaaaaa from git reflog. However, I couldn't get commit bbbbbbb because I didn't pull before git push -f.

I have tried git reflog in the remote repository, but there's nothing useful in reflog in the bare repository.

How can I restore the branch foo back to commit bbbbbbb in the remote repository?

(P.S. I don't know the actual value of bbbbbbb.)

Chindraba
  • 2,058
Lenik
  • 18,830

2 Answers2

14

The reflog of HEAD will indeed be useless, but each branch also has its own reflog; if you want to recover the branch foo, start with git reflog foo (or git log -g foo).

Even without a reflog, Git still retains the unused objects for several days (weeks?), so you can recover by finding the commit ID in some other way and manually reattaching it to a branch:

  1. Connect to the remote over SSH.

  2. Make a backup of the remote repository.

    tar -cvzf ~/project-backup.tgz /path/to/project.git
    
  3. Find the full-length commit ID of bbbbbbb. As long as you know the first few characters, you can use git show bbbbbb and/or git log bbbbbb to find out the full ID.

    $ git show bbbbbbb
    commit bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
    

    If you don't know the commit ID at all, then run git fsck and you should get a list of "dangling commits". Examine each commit using git show <id> and git log <id> until you find the correct one.

  4. Update the branch references:

    git update-ref refs/heads/master aaaaaaaaaaaaaaa...
    git update-ref refs/heads/foo    bbbbbbbbbbbbbbb...
    

    Manual method (less safe):

    echo aaaaaaaaaaaaaaa... > refs/heads/master
    echo bbbbbbbbbbbbbbb... > refs/heads/foo
    
  5. Check with git log master and git log foo (still on the server) to make sure that you restored the correct branches to the correct commit IDs.

grawity
  • 501,077
0

It is likely other services to also provide such. It is a day-saver.

akostadinov
  • 1,530