Hmmm, why shouldn't we be here for an subtree path? This method is only called from prescanOneTree() (when we ignore HEAD during clone or reset operations). There we create a non-recursive treewalk for merge, index and worktree and jump for every path into this method. In the clone use-case worktree and index should be empty, right? But during a reset it is likely that we are here because e.g. the worktree contains a folder for that path.

Now the good news: keep() tests for null values and therefore will not lead to an NPE.
And the bad news: f.isModified() doesn't test for null values and will NPE. So, I would guess this check is ok and needed.

I think we really need tests here. DirCacheCheckout.prescanTwoTrees is well tested. But prescanOneTree is not. I try to create some tests which improve test coverage.