As noted by other answerers, the concept of a default branch is a GitHub thing doesn't really make sense (in the lofty sense) of Git (there's a reasonably good (if under-appreciated) comment here gets into it a bit: https://stackoverflow.com/a/65710958/2521092) but in practice, we all know what that means.
Since the original asking of this question, Git 2.28 added init.defaultBranch
, allowing a different initial branch than master
, and a lot of projects are now using main
. That's good. Most of the answers here rely on checking a remote, but that relies on there actually being a remote, and that there exists a reliable and consistent naming scheme to those remotes. Those are probably (increasingly?) reasonable assumptions, but it's not a guarantee, and I don't find that any of the major answers here fail nicely.
Moreover, my main use case is using the name of the default branch for various git aliases (e.g. lm = log main..HEAD
). I'd like to use the same aliases without thinking about it too much, regardless of an external repo using master
or a local using main
with no remote. Git and its config can't really "store" information, so there's no way to set ahead of time what the current repository's main branch is. As such, any alias that wants to, say, show commits between the main branch and HEAD can't assume git log master..HEAD
or git log main..HEAD
will work.
Thus, I define a default-branch
alias in Git that figures out the default branch and then supply that to other aliases. This is a pain since a simple lm = log main..HEAD
has to instead become lm = "!git log $(git default-branch)..HEAD"
but here we are:
default-branch = "!git branch --sort=-refname | grep -o -m1 '\\b\\(main\\|master\\|dev\\)\\b'"
This simply gets the branch names then finds the first one in a defined list. If there's a main
, use that; if not and there's a master
, use that. I also have dev
in there as a tertiary option some folks use.
This is sort of similar to what @henrik-n does in https://stackoverflow.com/a/66622363/2521092, but I do it in Git itself rather than the shell, and I think it has some more optionality.