Skip to content

localrepo: Avoid getting all branches for default branch detection

To detect the default branch of a repo, we are currently getting all its branches and compare one by one. This approach is unnecessarily expensive, especially for repos having too many branches, giving HEAD is actually available for the vast majority of repos.

This commit adjusts the logic of GetDefaultBranch, we now prefer detection using git-rev-parse to exhaustion using git-for-each-ref.

For example, gitlab-org/gitlab has around 14,000 branches, getting all its branches took around 40ms for all refs packed in packed-refs.

  $ time git for-each-ref --format="%(refname)%00%(objectname)%00%(symref)" refs/heads/ >/dev/null

  real	0m0.042s
  user	0m0.032s
  sys	0m0.010s

And it's getting terribly bad for all loose-refs.

  $ time git for-each-ref --format="%(refname)%00%(objectname)%00%(symref)" refs/heads/ >/dev/null

  real	0m0.177s
  user	0m0.062s
  sys	0m0.111s

But it's much quicker to detect the existence of a branch.

  $ time git rev-parse --verify refs/heads/master >/dev/null

  real	0m0.003s
  user	0m0.002s
  sys	0m0.001s

In addition to the comparison of git commands mentioned above, we can also save more time and memory for not iterating and keeping the branches list.

Merge request reports