I wonder if the File argument here shouldn't be a little bit more flexible and try to guess what the caller wanted.

If the caller passes us the working directory and there is a .git within it, should we use the .git/ subdirectory instead of failing?

I think we should for this simple API. Most users of this API are going to try that first and get annoyed that they have to test for the .git/ subdirectory themselves.

If the caller needs precise control over how to find the .git/ directory, or wants the scan-up rules, they can use a RepositoryBuilder and wrap(). But those are more expert uses of the API.