Why does "git status" show I'm on the master branch and "git branch" does not in a newly created repository?

I upvoted two other answers, but I think the way to think of this is simple: You can be on a branch that doesn't exist. That's normal in a new empty repository, too, because for a branch name to exist, that branch name must identify the hash ID of an existing, valid commit. A new empty repository has no commits, so no branch names are allowed to exist yet.

Nonetheless, you are, initially, on some branch. The branch you are on is the one whose name is stored in the special name HEAD. In a new, empty repository, Git stores the name master (more precisely, refs/heads/master—the full name of the branch) in HEAD, so you are on master, while master does not exist.

You can change which non-existent branch you are on using git checkout -b:

$ git init
Initialized empty Git repository in [path]
$ git checkout -b asdf
Switched to a new branch 'asdf'
$ git checkout -b hello
Switched to a new branch 'hello'

Whenever you are on a branch that does not exist, the next commit you make creates the branch. This is also how git checkout --orphan works.


git branch shows nothing because there is no branch. But, as you can read in man git init:

This command creates an empty Git repository - basically a .git directory with subdirectories for objects, refs/heads, refs/tags, and template files. An initial HEAD file that references the HEAD of the master branch is also created.

I bolded the part I think is relevant - it looks like although there is no master branch yet, a reference to it already exists and that is why it is shown in git status. A proper branch will be created upon committing.


Existing answers address the literal question of why the output is what it is, but I think they've kind of glossed over the real issue...

You said you're automating something, so I would suggest that neither git status nor git branch is the best tool in a scripting context.

Some alternatives can be found in this discussion: How to programmatically determine the current checked out Git branch

Without knowing your needs (or how you would want an unborn branch to behave) I can't necessarily make a recommendation, but the point I'm getting at is, some commands are for human interaction (porcelain) and others are for scripts (plumbing)


The branch is unborn, yet. Therefore git branch doesn’t show it (git symbolic-ref HEAD indicates that your HEAD is pointing to the default branch master and that it is unborn as git branch doesn't show it, i.e., you can be on a branch that does not exist yet). However, committing something will create the branch.

This is also the case if you checkout an orphan branch.

I suppose git status shows the branch name as this is the branch which will be created.

For scripting see How to programmatically determine the current checked out Git branch