9

Here's the situation : some commits have been done in a remote repository.

Unfortunately, someone did push -f such that no remote branch references these commits anymore.

To make matters worse, I don't have those commits in my local clone.

My goal is basically to recover those commits. These are some of the things I tried :

  • git checkout -b recovery <commit_id> : fatal: reference is not a tree
  • git push origin <commit_id>:recovery

    error: refs/heads/recovery does not point to a valid object! error: unable to push to unqualified destination: recovery The destination refspec neither matches an existing ref on the remote nor begins with refs/, and we are unable to guess a prefix based on the source ref.

The repository is on bitbucket, and the commit is accessible from the web interface, so it hasn't been garbage-collected.

4 Answers 4

6

The problem is that your local repository doesn't have that commit id.

git checkout -b recovery <commit_id> git push origin <commit_id>:recovery 

Both of these commands fail for that reason, I get the exact same messages with a GitHub repo if I use a commit id that doesn't exist locally.

I thought the answer will be simply fetching the lost commits locally, in one of these ways:

git fetch origin #1 git fetch origin SHA1 #2 git fetch origin SHA1:refs/remotes/origin/recovery #3 

Unfortunately none of these work. It seems #2 used to work as of Git v1.4 according to this answer. As of now, it doesn't work anymore.

There is a help page for this on GitHub, but with no answer that you can use: it basically says that if you have the commit locally you can create a branch from it and push it. Yeah, but if you don't have the commit locally then what? It doesn't answer that.

I can think of two options:

  1. Find a teammate who has this commit. It's easy to check with git log SHA1. If anybody has it, they can create a branch from it with git branch recovery SHA1 and then push it.
  2. Contact bitbucket support. Since they have the commit, somewhere, they should be able to create a recovery branch for you.
Sign up to request clarification or add additional context in comments.

3 Comments

I just successfully performed #2 with git version 2.28.0.windows.1
#2 worked for me as well, using gitlab server
I confirm #2 worked for me with git 2.34.1 (Ubuntu 22.04.4). Server side, I had GitLab Enterprise Edition v16.9.1-ee. The commit was a merge commit from the pipeline of an open MR, which (AFAIK) is not garbage collected by GitLab, I think this is crucial. I tested #3 and it did not really work, it created a bogus reference to a non-existing recovery branch on origin, and the only way t get rid of it was git remote prune origin. What did work is a variation of #3: git fetch origin SHA1:NEW_BRANCH, which created a new branch called NEW_BRANCH in my local repo.
3

If you have the hash of the commit, then you can download the source tree from bitbucket with a link like this:

https://bitbucket.org/ownerName/repositoryName/get/A0B1C2D.zip 

Both .zip and .tar.gz work.

This doesn't recover the commit(s) exactly, but at least you won't lose the source code changes. I used this to simply create another commit with the same changes.

Comments

2

There is little trick - you said you have open the commit in web-interface. My version of the Stash has ability to create a tag on this commit. Look for "No tags [+]"

Comments

0

Just had to do this after deleting a branch too early on github and having no commit locally.

I was able to find the commit of interest in the CI/CD tool and having SHA256 was able to use github API with curl:

curl -L \ -X POST \ -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer <YOUR-TOKEN>" \ -H "X-GitHub-Api-Version: 2022-11-28" \ https://api.github.com/repos/OWNER/REPO/git/refs \ -d '{"ref":"refs/heads/featureA","sha":"aa218f56b14c9653891f9e74264a383fa43fefbd"}' 

worked right away, featureA was created.

for other API options you can check this page: https://docs.github.com/en/rest/git/refs?apiVersion=2022-11-28#create-a-reference

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.