Since short, GitHub proposes to use main
instead of master
for the default branch.
How can we get that name, for writing resilient Git aliases? How to get the default for the "master" branch in Git?
I've searched on SO, but none of the solutions in git - how to get default branch? does work reliably for me...
If I'm in branch feature
, forked from develop
, it will return me develop
and not master
(or main
, from which develop
is a fork)...
How to get that "master" branch name, then?
NOTE -- The question could be: why is git remote show origin
not showing me master
, but develop
instead, as the HEAD branch
?
You need to do this on GitHub, not on your local computer. If you go to the main repo page on GitHub and select the branches dropdown menu, you will see two branches listed and a checkmark next to master . We are going to change it so the default repo and the checkmark are next to the main branch.
You mention main
vs master
. Now, the first problem here is that there isn't really any default branch at the moment. There sort of is, but there's no guaranteed way to query it, because the "sort of" part is because there's no common agreement on this yet: not everyone has Git version 2.28 or later installed.
That said, running:
git config --get init.defaultBranch
may produce something in your own Git repository, and if it does and if your Git is 2.28 or later, your Git will use that as the default name for the unborn branch when running git init
. (See also commit 8747ebb7cde9e90d20794c06e6806f75cd540142.)
Note that if someone runs:
git init --initial-branch=xyzzy
to create a new, empty repository, the name of the unborn branch in this new, empty repository will be xyzzy
, regardless of whether there is an init.defaultBranch
setting, and regardless of what might be in it. The --initial-branch
option also first appears in Git 2.28.
You also asked, regarding answers to git - how to get default branch?:
The question could be: why is
git remote show origin
not showing memaster
, butdevelop
instead, as theHEAD branch
?
The git remote show
command, and the git ls-remote
command (try it), work by calling up some other Git repository and getting information from it. Before we discuss this information, let's take a look at how HEAD
works in your repository.
A Git repository is, at its heart, a collection of commits. Each commit is numbered with a unique hash ID. All Git systems everywhere use a particular algorithm—currently SHA-1, but there are plans to switch to SHA-256—to compute the hash ID of a commit based on the commit's content, so that all Git systems will come up with the same hash ID for the same commit.
This is how Git works in term of distributing commits. Each repository has a full collection of its own commits. When you cross-connect a pair of Git repositories, such as your own and one over on a system your Git calls origin
, they exchange hash IDs. Since the hash IDs uniquely identify the commits, the sender can list a hash ID, and the receiver can immediately tell from that whether he has the commit, or needs the commit. Add in some optimizations based on the commit graph structure and we have most of what we need for the have/want protocol exchange.
Each Git, though, finds commits in its own repository using names: branch names, tag names, and other such names. These come with hash IDs, which find some particular commit. Those commits then find any earlier commits as well.
For the purpose of sending commits, the sending Git in a git fetch
pair-up lists out his branch and tag and other such names, so that the receiving Git can figure out which commits to ask for, if any. You can list out your own names—all of them or some selected subset—using git for-each-ref
. The default is to list all names that start with refs/
.
There is one piece missing from the above picture, and that's the special name HEAD
. This special name—it doesn't start with refs/
and Git uses it internally all over the place in various special ways—is normally what Git calls a symbolic ref, and we can read it with git symbolic-ref
:
$ git symbolic-ref HEAD
refs/heads/master
This tells us that in this particular Git repository, the current branch is the one named master
. (Branch names all start with refs/heads/
; other names start with other refs/
-based prefixes.) In a non-bare Git repository—the kind that we normally work with—this means someone has run git checkout master
or git switch master
.
When we use git ls-remote
to connect to some other Git, their Git will run git for-each-ref
for us, to list out their names. But they prefix their list with the value in HEAD
, and if we add the --symref
option,1 we get their HEAD
in two ways:
ref: refs/heads/master HEAD
72c4083ddf91b489b7b7b812df67ee8842177d98 HEAD
71ca53e8125e36efbda17293c50027d31681a41f refs/heads/maint
72c4083ddf91b489b7b7b812df67ee8842177d98 refs/heads/master
a3ce27912f980d787926b113d17f1f532e50162a refs/heads/next
[snip]
So this tells me that their Git repository has master
as their HEAD
. The first output line makes this clear directly; the next few lines show me that their HEAD
and their refs/heads/master
both refer to commit 72c4083ddf91b489b7b7b812df67ee8842177d98
, which is less direct.2
The git remote show
command has the ability to call up the other Git.3 This means they can have them list out which branch they have as their HEAD
. When you see:
HEAD branch: develop
this merely means that their Git has their HEAD
attached to their branch name develop
. If their repository is non-bare, this means they ran git checkout develop
or git switch develop
.
If they have a bare repository, they can still get the same effect, using git --work-tree=... checkout
, or GIT_WORK_TREE=... git checkout
, or by running git symbolic-ref
directly. The branch name to which their HEAD
is attached is not necessarily their master
or their main
, if they have one: they control which branch name, if any, is stored in their HEAD
.
There is very little significance attached to this. If their HEAD
names their develop
, that just means that their HEAD
is attached to their develop
. Since their branch names are theirs—not yours—this shouldn't matter to you.
There is one place where it does matter, though. If you run:
git clone <url>
instead of, say:
git clone -b somebranch <url>
then you're asking your Git to call up their Git and ask them which branch name they recommend. When you supply -b branch
, you're choosing the branch; when you don't, you're telling your Git to follow their recommendation. The recommended branch name is the one to which their HEAD
is attached. So they—whoever they are, in control of this other Git repository—should use whatever means they have at their disposal to connect their HEAD
to the branch name they personally recommend.
There's no need for you to follow their recommendations. Your clone has your branch names in it. You do not need to use the same names they are using. That's up to you. Most people do mostly use the same names, to make things easier to think about.
1This --symref
option is not supported in older versions of Git. When a newer Git is talking to an old Git that can't do symbolic ref transfers, the newer Git has to guess about the older Git's HEAD
. This is a somewhat ugly situation and we will just assume that you're using all-newer-Git-versions here.
2This shows you how older Gits can guess: if the hash ID from HEAD
matches exactly one branch name, that tells us that this is the branch name. But what if the hash ID from HEAD
matches two, or three, or more, branch name hash IDs? That's where the situation becomes ugly.
3In modern Git, that's the default for the way you are using git remote show
. I'm not sure if this was ever not the default. The git remote
command has a lot of sub-commands though, and many of them don't bother calling up some other Git.
This doesn't answer the question itself, but pragmatically the core problem is determining whether a repo uses the main
or master
naming standard. As such, in most cases we can do this:
git branch | grep -o -m1 "\b\(master\|main\)\b"
-o
— print only the match-m1
— print only the first matchTo get the default branch name for a git repository that uses Github, install the gh
command, built by Github. Then run
cd agithubrepo/
gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name'
Example output:
main
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With