How to get Phabricator to realize Git repos are there again in storage?

This is almost certainly not a bug with Phabricator, but rather a weird scenario I’ve gotten into and I’m wondering how best to get out.

I have Git repos that are actually not on the Phabricator server itself but rather mounted from an NFS share. The system that serves those NFS shares has been having some weird problems with I/O stalls, and somehow as a result Phabricator seems to think all the Git repos its set up to host are empty—despite all the files still being there (or perhaps more accurately, being ‘there’ again in that the NFS mount is available again) and currently accessible. Or at least I think they’re all there; I can’t say I’m hugely familiar with how Git server-side storage should look, but the sheer size of the data remaining would seem to imply it.

Perhaps I could just manually re-import the repos in some way or another, but if there’s any way to just get Phabricator to realize the repos are all still actually there and not empty, that’d be very nice! I looked at the arguments for phabricator/bin/repository but I didn’t see anything that seemed applicable other than reparse, which just gave a long list of warnings along the lines of

 WARN  Commit "rBPPARSE5f31c73eff922d34a72b42dfdb9b309ac07c9528" (with internal ID "248866") is no longer reachable from any branch, tag, or ref in this repository, so it will not be imported. This usually means that the branch the commit was on was deleted or overwritten.

Phabricator always “sets” the repository state to the state on disk, so no intervention should be required (nor is any intervention possible).

This is necessary in the general case, because Phabricator may be configured to observe a repository where the writable copy is hosted elsewhere, and the writable copy may be mutated freely. For example, you can:

  • Host a repository on GitHub.
  • Observe the repository with Phabricator.
  • Delete the entire repository history.
  • Restore the repository history, or replace it with a completely different repository.

Phabricator should handle this kind of situation cleanly. (And, for purposes of importing commits, writable and observed repositories are treated the same way.)

The only exception is that Phabricator will remember commits it previously saw that are no longer part of the repository. A major goal here is so that you don’t lose all your audit history, comments, build information, etc., if someone accidentally deletes master. Instead, the commits will be marked “unreachable” (and still accessible in the web UI, just with a warning), and then marked “reachable” again if master is later restored.

Thus, the warning you ran into is expected if a repository has had commits removed from it. (This is common if you track “temporary” branches, like “epriestley-tmp-bugfix-123”.)

You can test the reachability of a commit by running this command from Phabricator’s working copy on the server:

$ git for-each-ref --contains <hash>

For example, you may see output like this (1d4d86 is the current HEAD of upstream master in Phabricator at time of writing):

$ git for-each-ref --contains 1d4d860cb5a0f09cd136495c120a44e02885d5c5
1d4d860cb5a0f09cd136495c120a44e02885d5c5 commit	refs/heads/master
1ad81b491f4d8483758a49a07311de64b6a2832a commit	refs/heads/publish1
86827e5cd6333cc5971b17b05d8e536b342dd679 commit	refs/heads/publish10
a688df591320c5fe5f620ebeb77c618eed9b11ea commit	refs/heads/publish11
3ebf64ccdabb6b3f84a6590078fb378e3f3cb509 commit	refs/heads/publish12
35e972d8b8d5612e53e9b7bad1cc2e21229d61dc commit	refs/heads/publish13
97c84361bf9e04d6bfd44767af203746a34fa0ad commit	refs/heads/publish14
882dd8f6617c10098f457ed34dc2fd691b0ff2ca commit	refs/heads/publish15
882dd8f6617c10098f457ed34dc2fd691b0ff2ca commit	refs/heads/publish16
c96eccf9d7566511f3c746b53f2e816af3ab42a7 commit	refs/heads/publish1x
ee861bfc700de53798eaa4ab9b7ff92cdb6f6c3b commit	refs/heads/publish2
8e383454ddb880e04c66e7715eedc83673fc78a2 commit	refs/heads/publish3
dee2199058ee5a541894705b847fc5c1bf9b3f8d commit	refs/heads/publish4
0da68ad1821c043f24d54c02ee87692d30dffce6 commit	refs/heads/publish4x
a13c5d65d7352ba418d7f629def0f668a4aaf23a commit	refs/heads/publish5
2cf8d3bb931417915d94f99a8951d108ad4d774e commit	refs/heads/publish5x
758656ea6ff46cde9035587a92f5fa6cfb33e2e3 commit	refs/heads/publish6
e86cd6030be32a5334116e1df126b28372123e12 commit	refs/heads/publish6x
03ce1bee2155085f3507f20fc1e71c25d1a6d2be commit	refs/heads/publish7
83f4507ba4326b18c9ac5f35abadc3defa92d653 commit	refs/heads/publish8
5cfd8b402c1e463915188c43dafad7daa483c46f commit	refs/heads/publish9
2710a1e7aa426b6a3bfc68f90a968e492bee0b59 commit	refs/heads/stable
1d4d860cb5a0f09cd136495c120a44e02885d5c5 commit	refs/remotes/origin/HEAD
1d4d860cb5a0f09cd136495c120a44e02885d5c5 commit	refs/remotes/origin/master
2710a1e7aa426b6a3bfc68f90a968e492bee0b59 commit	refs/remotes/origin/stable

This is showing that 1d4d86 is an ancestor of all these branches. Since it’s an ancestor of at least one ref, it’s “reachable”.

If you push a change to “tmp-epriestley-bugfix-123” and later delete that branch, the commit will no longer be an ancestor of any branch, tag, or ref, and will be “unreachable”. This is normal if you do not treat the remote as append-only, and not indicative of a storage problem.

1 Like

Thanks! That does help clarify a lot for me, although I still remain a bit baffled because in fact if I run this:

keithzg@serrano:/var/repo/80$ git for-each-ref --contains 5f31c73eff922d34a72b42dfdb9b309ac07c9528
9570e2e99d51818c1971f5a6c05cea92da76d7e9 commit refs/heads/master

well that’s as expected if I’m understanding this right, as that’s in fact the most recent commit I made and pushed to this particular repo before things went to hell on our file storage server, and it was indeed right to master. Yet over in Phabricator I see:

No Default Branch
This repository is configured with default branch “master” but there is no branch with that name in this repository.

That isn’t supposed to happen and I don’t know how to reproduce it. I’d expect the web UI to either show master or fail with an error given that refs/heads/master exists when you run git for-each-ref.

I’m going to chalk this one up to the continuing very mysterious problems I’m having with the network storage the repos are being stored on, because after applying some more updates to both the Phabricator server and the storage server and rebooting the latter now the repositories are showing up fine, with their full histories. Even more proof that the problem is not Phabricator, and also proves it’s fixable without doing having to manually do anything to Phabricator. Back to me trying to figure out why the storage server is having such issues, I guess . . .

Thank you very much for your help! And also for Phabricator’s continued existence, it definitely makes my life a lot better :slight_smile: