3

Sometime in the past 6 weeks an issue has been introduced into the codebase. I have identified which branch introduced it (and the head/tail commits for that branch) but I would now like to start tracing through the individual commits on that branch to identify the exact cause.

My problems are that:

  1. The branch in question was deleted by the build-server after being merged to master
  2. Before merging, the commits were squashed (by the build server).
  3. I don't have access to the local environment where the commits were originally made and pushed from.

I can see the commit history for the now-deleted branch on our build-server but if I try to checkout one of them locally I just get the error

error: pathspec '<commit-id>' did not match any file(s) known to git

The build-server is also happy to show me the diffs for each commit which implies they are still in git somewhere (or alternatively the build-server has cached them, but that seems unlikely).

I've seen references to git reflog but that seems only to work on the local repository history (or, more likely, I've failed to find some advanced option it offers).

Is there a way to do this? TIA.

NeilMacMullen
  • 3,339
  • 2
  • 20
  • 22
  • 1
    I found this. Not sure if this would help but the trick is identifying the last commit for the branch: https://stackoverflow.com/questions/3640764/can-i-recover-a-branch-after-its-deletion-in-git#:~:text=Yes%2C%20you%20should%20be%20able,recreate%20the%20branch%20from%20there. – astrochun Apr 22 '21 at 14:47
  • Alas, i think that doesn't work because the branch deletion/squash happened on the build server and isn't available in local history. I'll edit the OP to make that clearer. – NeilMacMullen Apr 22 '21 at 15:01

1 Answers1

4

I can see the commit history for the now-deleted branch on our build-server...

Log into the build server, and create a new branch from the latest commit ID before the squash and push it:

git branch investigation-branch 1234abcd # use the last commit id before the squash
git push origin investigation-branch # assuming your remote is "origin"

Now fetch from your local machine and you should be able to see that branch as it was previously. You can simply delete the branch on the remote when you're done investigating, if you wish.

Note: if you prefer not to log into the build server, it's possible that another machine has the commits too. The places that might still have them are:

  1. The original machine that pushed the commits. (Already ruled out that you can't access this.)
  2. The build server. (Confirmed.)
  3. Any machine that fetched the repo during the time window where those commits existed on the branch and haven't been garbage collected yet. The longer the desired commits existed on the branch before getting squashed, the greater the probability that they were fetched by another machine. Note the default garbage collection for orphaned commits is 90 days so 6 weeks ago is well within the default time window, though it's possible to manually run commands to clean up your local repo and blow away those orphaned commits sooner.
  4. Do you use a centralized Repository? If yes, it should still have a copy of the unreferenced commits and there may be a mechanism for accessing them. Some tools even allow you to create a new branch from any historical commit, directly from the UI. This would essentially accomplish your goal without having to log into the server to do it manually.
TTT
  • 22,611
  • 8
  • 63
  • 69
  • Thanks, that's an excellent suggestion and will mark it as an answer later if no-one can come up with a way of doing this directly without requiring access to the build server. – NeilMacMullen Apr 22 '21 at 15:00
  • 1
    @NeilMacMullen I added some more information that may help. I think you'll need to log into *something* that has those commits. AFAIK there isn't a way to run a command on your machine that can request unreferenced commits from another. Though some tooling offers the ability to create branches (or maybe tags?) from specific commits that it can see, which would re-reference them and make them available again for all. – TTT Apr 22 '21 at 15:35
  • 1
    If the build server has access to the commit, hopefully it got it from some central repository. If the central repo is a known git service (e.g : Github, Bitbucket ...) or even a self hosted version of gitlab, look into the docs of that service : some offer access to their reflog through API calls. – LeGEC Apr 22 '21 at 15:47
  • @LeGEC indeed, I was hoping that because the build server could clearly see these things in the main repo, I would be able to get at them too from the git client. But maybe the squash operation dereferences commits and the build-server (azure devops) is just using some other mechanism to retrieve the diffs. – NeilMacMullen Apr 23 '21 at 08:07
  • @TTT - accepted, thanks! If you happen to know that for a fact that 'squash' dereferences commits and therefore makes them invisible downstream that would be a useful thing to explicitly spell out. It's kind of implicit in your answer but would make it clearer why my original attempt to use the git client wouldn't work. – NeilMacMullen Apr 23 '21 at 08:11
  • 1
    @NeilMacMullen Is your repo in Azure DevOps? If yes, then #4 is the way to go. In Azure Devops, navigate to any branch, click on any commit which will open the view of that commit. Then modify the URL to replace the commit ID with your desired commit ID. Now that you're viewing the commit, on the right side select the three dots, then "New branch...". It will make a new branch on the server based on that commit, which you can then fetch. – TTT Apr 23 '21 at 15:06
  • @TTT - yes. Sorry I should have said earlier I managed to get the branch based on your previous answer so all sorted now :-) – NeilMacMullen Apr 23 '21 at 16:07