The problem bisects down to c931ba4e (sha1-name.c: remove the_repo from handle_one_ref(), 2019-04-16), which did this: - for_each_ref(handle_one_ref, &list); - head_ref(handle_one_ref, &list); + cb.repo = repo; + cb.list = &list; + refs_for_each_ref(repo->refs, handle_one_ref, &cb); + refs_head_ref(repo->refs, handle_one_ref, &cb); The old code used the helper for_each_ref(). This is a thin wrapper around refs_for_each_ref() and allows the default repository object to be used implicitly by the caller. It is understandable that the code wanted to work on arbitrary repository object, and replaced the for_each_ref() helper with refs_for_each_ref() helper that takes any ref store object. But there is a small mistake. for_each_ref() makes sure that the ref store is initialized; the new code blindly assumes it has already been initialized. int for_each_ref(each_ref_fn fn, void *cb_data) { return refs_for_each_ref(get_main_ref_store(the_repository), fn, cb_data); } So, I think the fix is simple. With the attached one liner on top of c931ba4e (sha1-name.c: remove the_repo from handle_one_ref(), 2019-04-16), $ git rev-parse :/any/path/ no longer segfaults. I think it would also work just fine when merged to more modern codebase, but I haven't tried it (yet). sha1-name.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sha1-name.c b/sha1-name.c index d9050776dd..3aba62938f 100644 --- a/sha1-name.c +++ b/sha1-name.c @@ -1771,7 +1771,7 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo, cb.repo = repo; cb.list = &list; - refs_for_each_ref(repo->refs, handle_one_ref, &cb); + refs_for_each_ref(get_main_ref_store(repo), handle_one_ref, &cb); refs_head_ref(repo->refs, handle_one_ref, &cb); commit_list_sort_by_date(&list); return get_oid_oneline(repo, name + 2, oid, list);