4

I have done a git push -f on a branch and now lost the other persons work.

I could able to see in my github that the other person work is shown (shown in activity), but not in the remote branch (where I pushed my changes). Unfortunately I don't have my local repo sync up with remote. So I don't have other persons code in my local. Is there a way I can get that to my local and recover?

sashoalm
  • 75,001
  • 122
  • 434
  • 781
Ant's
  • 13,545
  • 27
  • 98
  • 148
  • 1
    ... Don't do `push -f`. If git complains about conflicts, assume it knows best and fix the conflicts – Panagiotis Kanavos Sep 14 '16 at 13:13
  • @sashoalm: There is no other way ? – Ant's Sep 14 '16 at 13:14
  • Do you know the hash of the lost commit? Does this commit persists in your local repo after fetch? – Denys Kurochkin Sep 14 '16 at 13:20
  • 1
    Make a new clone and run `git fsck --no-reflogs` to find all the dangling commits. One of these dangling commits was pointed to by the branch before the force push. If no dangling commit is listed, that commit is referred to by some other branch or tag. You could try to find it out. I'm not using Github, but I think I've heard from someone that Github has a feature to record things like reflogs. – ElpieKay Sep 14 '16 at 13:24
  • Similar - http://stackoverflow.com/questions/34246207/recovering-file-history-after-a-forced-push?noredirect=1&lq=1 – sashoalm Sep 14 '16 at 13:39
  • @ElpieKay Apparently [dangling commits can't be cloned](http://superuser.com/a/335059/66282). And since he's on GitHub, he doesn't have direct filesystem-level access to the bare repo so he can't run `git fsck --no-reflogs` on it directly. – sashoalm Sep 14 '16 at 14:38
  • @sashoalm I wonder if you have ever tested to clone a repo with dangling commits before. You can have a try with both bare and non-bare repos. Apparently dangling commits can be cloned from one local repo to another local repo with Git 2.8.0.windows.1 or 2.5.0.linux. – ElpieKay Sep 14 '16 at 15:27
  • @ElpieKay From one local repo to another, yes. According to http://stackoverflow.com/a/6865218/492336 this works only when the remote repo is on your own computer or a shared drive, i.e. when you are using the file:// protocol instead of ssh:// or git://. But if you've tested it works when fetching from a remote GitHub repo and verified it works I'll just trust you. – sashoalm Sep 14 '16 at 15:49
  • @ElpieKay Ok, I tested it for GitHub and it didn't work. I pushed a test commit, copied the SHA1, then did `git reset --hard HEAD~1` followed by `git push -f`, and then cloned the repo. I tried checking out the commit directly by its SHA1 and it wasn't there. So I assume it really depends on the protocol you use. – sashoalm Sep 14 '16 at 16:08
  • @sashoalm well your first link does not tell the whole story. But anyway thank you for your sharing. – ElpieKay Sep 14 '16 at 16:10

3 Answers3

4

Before doing anything else, please do these 3 steps - backup your local repo, tell the other guy to backup his, and backup the remote repo as they are now. Nothing fancy, just Ctrl+C, Ctrl+V would do. Do it on your entire project so you backup the working tree as well. If you don't have direct access to the remote server, a git clone would have to suffice, though I would prefer a real directory copy.

Once you've done that, the other guy can use git push -f to reupload his branch. If he has new commits, you will have to figure out which commit was last pushed by him, but I'm fairly sure no actual commits will be lost. If the other guy has done git pull -f, even then he can use git reflog to recover his local branch.

Since you're using Github, you might also see https://stackoverflow.com/a/35273807/492336. Apparently there is a Github’s Events API which might be useful.

Community
  • 1
  • 1
sashoalm
  • 75,001
  • 122
  • 434
  • 781
3

You can access to GitHub's reflog via REST-API

This will show you events:

$ curl https://api.github.com/repos/<user>/<repo>/events

After you've found broken commit just add a reference to it:

POST /repos/<user>/<repo>/git/refs
{
  "ref": "refs/heads/featureA",
  "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd"
}

or with curl:

$ curl -i -H "Accept: application/json" -H "Content-Type: application/json" \
    -X POST -d '{"ref":"refs/heads/featureA", \
                 "sha":"aa218f56b14c9653891f9e74264a383fa43fefbd"}' \
    https://api.github.com/repos/<user>/<repo>/git/refs
Denys Kurochkin
  • 1,360
  • 1
  • 18
  • 34
-6

I am not a git user, but few days ago I came a cross this post, I guess this one has solution to your problem as well.

http://ohshitgit.com/

# undo the last commit, but leave the changes available
git reset HEAD~ --soft
git stash
# move to the correct branch
git checkout name-of-the-correct-branch
git stash pop
git add . # or add individual files
git commit -m "your message here"
# now your changes are on the correct branch
tssutha
  • 99
  • 8