83

I'm trying to automate a process and issue the git branch command to find out what branch I am on. Everything is working fine except for a newly initialized repo where git branch returns nothing. Given I've done nothing with the repo, not even the initial commit, I can accept the answer. However, if I run a git status it tells me I'm on the master branch, as seen here:

$ mkdir todelete
$ cd todelete
$ git init
Initialized empty Git repository in /u/u70021a/todelete/.git
$ git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)
$ git branch
$

Am I doing something wrong? Is there some setting I haven't set properly?

I also have a number of new people to Git and I can't explain to them why the command to show which branch they are on shows nothing, yet the status command does.

Ryan Prechel
  • 6,592
  • 5
  • 23
  • 21
GOVarney
  • 1,027
  • 1
  • 7
  • 9

5 Answers5

95

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.

torek
  • 448,244
  • 59
  • 642
  • 775
  • 6
    Thanks. While I don't agree with what git is displaying. At least I understand why. Your checkout example is interesting. According to the documentation for "git checkout" the -b means: **Create a new branch named ** which isn't strictly true. In your example, neither branch asdf or hello are actually created. But they will be if a commit is performed. My personal opinion is the "On branch master" message should be changed to "Next Commit to branch master" because until a commit is performed the master branch doesn't exist. – GOVarney Jul 16 '19 at 08:16
  • 2
    I'm not sure if this is relevant to your case or not, but I want to point that for Git it is possible to not be on any branch at all. – sklott Jul 17 '19 at 06:08
  • Git internally uses `cat .git/HEAD` to see what branch it is on, figuring out of the branch exists would consume more CPU and disk time, so that's probably why they didn't do it – Ferrybig Jul 17 '19 at 09:42
  • What should imo be mentioned is that you should not use `git branch` in an automated process at all because it's not designed for that use case. It would be interesting to see what the non-porcelain commands show here, does `git symbolic-ref --short HEAD` have the same behavior? – Voo Jul 17 '19 at 17:18
  • @Voo: `git symbolic-ref` shows the name contained in `HEAD` (hence the orphan/unborn branch reference) provided that `HEAD` is not detached. In a new empty repository, `HEAD` *cannot* be detached as a detached HEAD must contain the hash ID of an existing, valid commit. (In a nonempty repository, with a detached HEAD, `git symbolic-ref` produces an error.) – torek Jul 17 '19 at 17:33
  • @GOVarney: "I don't agree with what git is displaying." IMO, Git's wording is valid, because you're already in the flow of one branch automatically jumping forward to the next future commit. Imagine if you made 5 new branches from one commit. If you checkout one, you effectively checkout all 5, but only one of them will jump forward when you make a commit. Being on a branch is not the same as checking out a commit. – luther Jul 18 '19 at 16:19
23

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.

Stanowczo
  • 753
  • 5
  • 21
  • 3
    So it looks like "git status" is just displaying the "branch name" as seen in **.git/HEAD** (ref: refs/heads/master) but does no consistency check by looking in **.git/refs/heads** to see if it actually exists. – GOVarney Jul 16 '19 at 07:08
  • I cannot tell for sure, as I didn't inspect git's code, but what you wrote makes sense to me. But still I prefer torek's answer over mine :) . – Stanowczo Jul 16 '19 at 07:14
17

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)

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
15

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

MrTux
  • 32,350
  • 30
  • 109
  • 146
2

In git the default branch is master. When you commit git will "use" the current branch which you on right now. Since you have initialized a new repository you are on the "default" branch and this is why you don't see it in your branches list, it will show up once you commit your changes.

enter image description here

enter image description here

CodeWizard
  • 128,036
  • 21
  • 144
  • 167
  • 2
    I understand branching, I don't understand why "git status" says I'm on a branch that doesn't exist. – GOVarney Jul 16 '19 at 06:53