rOpenSci | Don't Lose your HEAD over Default Branches

Don't Lose your HEAD over Default Branches

Did you know that GitHub lets you refer to the default branch of any repository by substituting the branch name with HEAD in the url? This is a very useful trick to write robust code that works regardless of whether the default branch is called main or master, and will keep working when the default branch gets renamed at some point.

While git has no “default” branch, online code platforms such as GitHub need to define a default for the branch that someone sees when they look at code online. While the community standard for the default branch is now becoming main instead of master1, and while the switch for any repo is rather easy and is well supported by usethis, for a while (forever) there will still be repos with different default branches in the wild.2 Especially as nothing prevents you from using any other name for the default branch (although this could trip up collaborators).3

So, what to deal with the existence of different possible default branches?

gert::git_remote_ls() |>
  head() # another useful thing named head
#>                           ref          symref
#> 1                        HEAD refs/heads/main
#> 2        refs/heads/1password            <NA>
#> 3              refs/heads/2fa            <NA>
#> 4            refs/heads/email            <NA>
#> 5 refs/heads/fix_author_links            <NA>
#> 6        refs/heads/footnotes            <NA>
#>                                        oid
#> 1 2ef29132be682883d1c12a957c38e1fa6599898f
#> 2 e4f3ef36c453dd2ede5a091c7d3f5f32c609caca
#> 3 7461f15e81651d5bbf6dcab078801cfa35e2f039
#> 4 6f8c849ef325dc597e819bffbd8829afa05ae414
#> 5 2f328db8fc6ce94caa50ddde7a0b021178818d8f
#> 6 f552c2dcac79228e929e65975c52484f5655577c

gert::git_remote_info() shows the head for a given remote:

gert::git_remote_info("origin")
#> $name
#> [1] "origin"
#> 
#> $url
#> [1] "[email protected]:ropensci/roweb3.git"
#> 
#> $push_url
#> NULL
#> 
#> $head
#> [1] "refs/remotes/origin/main"
#> 
#> $fetch
#> [1] "+refs/heads/*:refs/remotes/origin/*"
#> 
#> $push
#> character(0)
  • When linking to a file, or trying to download the same path from a gaggle of repositories, think of the HEAD reference! I.e. instead of linking to a file via https://github.com/<owner>/<repo>/tree/<default-branch>/<path> where you need to know what the default branch is, you can link to https://github.com/<owner>/<repo>/tree/HEAD/<path> that will always point to the latest version of the path in the default branch. Similarly, for raw content (to download), you can use links à la https://github.com/<owner>/<repo>/raw/HEAD/<path>.

In conclusion, master or main? Hit the nail on the HEAD. 😉


  1. For more context on Terminology, Power and Oppressive Language see for instance https://tools.ietf.org/id/draft-knodel-terminology-00.html ↩︎

  2. Actually, this post was the occasion to change the default branch for the source of this website! ↩︎

  3. Some repos only have a branch called gh-pages (e.g. everything under https://github.com/ropensci-docs), in which case that is the default branch. ↩︎