Search code examples
gitrestore

git find commit from "working tree"


Suppose a person cloned a git repository and deleted the .git folder. Is there a way to recover which commit they were on? This isn't a duplicate of Best way to restore .git folder or Can deleted .git be restored?, because years have past since this event. I'm now trying get it back under git to update it to a new version. However, changes may have been introduced in those years, that I need to merge/rebase onto the new version.

My current idea is to:

  1. Clone the current repository from github into another folder using git clone --bare
  2. Mark the repo as non-bare using git config --local --bool core.bare false
  3. Copy the files from the mystery version into this folder
  4. Save a diff of the working tree with the current commit hash somewhere
  5. Update HEAD to HEAD^ (Not really sure how to do this step without modifying the working tree. Potentially switching back to bare, checkout HEAD^ switch back to non-bare? I've also read about git symbolic-ref plumbing but don't know how to use it)
  6. Repeat steps 4-5 until at root
  7. Choose the diff with the smallest size. That should be a good approximation to the commit that this code diverged from. Search around that commit for the exact divergence point.

Is there a better way? There's a semver, but it wasn't updated very much so it only cuts down the range to around a year or two. I don't believe the repository was changed much, so I'd guess there are exact matching files. Maybe I could use that information to narrow down the possible commits? Thanks!


Solution

  • I would do:

    1. commit the actual sources into some branch (e.g. _tmp_), so that index is clean

    2. iterate over all possible commits (e.g. git rev-list master) and check the diff

      git rev-list master | while read rev; do git diff "$rev" "_tmp" && echo "it is $rev!" done

      When _tmp_ contains files which are untracked in the repository, the git diff will never succeeded and you have to analyze the diffs (e.g. this with lowest wc -l wins).