I am new to git and was following the following excellent instruction from Missing Semester. About 1 hour in, they discuss remotes. I went through the process of creating a remote (as a sub-directory for testing), however, I purposefully deviated from the instructions because that helps my understanding. I pushed a branch to the remote but did not name it "master". I eventually realized there was no HEAD in this remote, and things just didn't work right. I looked at the git remote set-head command, and thought that would solve the problem. I don't think it did. What eventually worked was creating a branch called "master" on the remote, and HEAD automatically pointed to it. I did not see this requirement in the documentation. Is there a way to have a repository without a branch named "master"? Alternatively, if there is no branch named "master", how does one get the HEAD pointing to a branch after the remote is created?
-
2The problem is that your question is full of unexplained meaningless phrases like “and things just didn't work right” and “solve the problem” and “worked”. Please say explicitly what you did and what happened. Otherwise we have no idea what “problem” we are supposed to “solve”. (Quite similar to yesterday where you talked all around the problem without showing the git log that revealed the whole matter instantly.) From what little I can gather this seems a pure duplicate of https://stackoverflow.com/q/8839958/341994 but it is hard to know. – matt May 31 '20 at 11:19
-
Also on slightly different but related topic, you have asked a dozen questions on Stack Overflow that have garnered answers, but only once have you ever _accepted_ an answer. That is a poor showing. Answer acceptance is the coin of the realm on Stack Overflow; it costs you nothing (in fact, you gain by it) but you are not paying your dues. As a good citizen you really ought to review your questions and see whether any answer can be accepted for each one. If so, accept it. If not, consider whether the question may have been poor, and perhaps improve it to be answerable. – matt May 31 '20 at 14:17
-
Matt, I appreciate this comment. I just accepted an answer, an excellent one. I did not know that was expected, but I am learning. – Anthony Mannucci May 31 '20 at 15:51
-
One symptom of the problem was that doing a "git log ---graph --decorate --all" command in the repository directory would show a commit history, but did not show a HEAD anywhere. Branches were identified etc., but one did not see the characters "HEAD ->" anywhere. This was consistent with following error messages, which it is true, I have not captured here. – Anthony Mannucci May 31 '20 at 16:07
-
That's great but, as with your previous question, that info should have been (and still should be) _in the question_. – matt May 31 '20 at 16:40
-
My question is really contained in the last two sentences. The other information is for background. I felt the details did not matter. Perhaps I should not have included that background. – Anthony Mannucci May 31 '20 at 17:28
-
What I'm suggesting is that you do not know what infomation to omit in order to ask a good question. I've had the same problem with your two most recent questions; I have not looked at any others. We always need to be able to reproduce the exact issue. Therefore we need to know what you did, what happened, and what you expected. This may sound like a time-consuming tedious way to construct a question, and it probably is. So what? Handwaving roundabout descriptions of the general area in which the difficulty occurred are not good questions. You can take my advice or leave it, of course. – matt May 31 '20 at 17:31
-
Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/215055/discussion-between-anthony-mannucci-and-matt). – Anthony Mannucci Jun 01 '20 at 00:54
1 Answers
TL;DR: you need to reach into the server (somehow—the how depends on the server) and have the server's Git set its HEAD
. (Note that GitHub have a clicky web button interface for this, under settings
and then branches
.)
Usually, though, you just start by having the server create its first branch having the name master
, after which everything works the way everyone expects. Note that if a server Git already has a branch named br1
, you can clone that server Git repository with:
git clone -b br1 url
on your client side, followed by:
git push origin br1:master
to ask that server to create the name master
, pointing to the same commit as your own br1
in your clone. Now the server does have a master
and all is back to normal.
Long: what, exactly, is going on here?
Every Git repository has a HEAD
All Git repositories have a HEAD. This is a basic requirement of Git: when Git goes to look for a repository, it makes several sanity checks on each directory it inspects. The directory must:
- exist as a directory;
- contain a file or symlink named
HEAD
that appears valid; - have a
refs/
sub-directory; and - have an
objects/
sub-directory (unless overridden by settingGIT_OBJECTS_DIRECTORY
in the environment).
Failing any one of these tests makes Git move on to the next candidate for a repository directory, or, if it has run out of candidates, give up and declare that there is no Git repository to be found.
The code that does this checking is in setup.c. The is_valid_ref
test is elsewhere (path.c
) and basically tests whether HEAD
is a symbolic link to refs/*
, or starts with the literal ASCII text ref: refs/
, or contains a valid hash ID. The first two tests are the same as testing whether a reference is a symbolic ref (see the git symbolic-ref
command).
A HEAD
file that contains a commit hash ID is a detached HEAD. This indicates that the Git repository is not on a branch at all. There is little more to be said about this (until we get to cloning, below, anyway). To set a detached HEAD in a repository in which you can run Git commands directly, use git switch --detach
or git checkout --detach
or git checkout
with any argument that automatically causes a detached HEAD condition, i.e., any reference to a commit that is not literally a branch name.
(There is no way to set a detached HEAD with the GitHub web interface.)
A symbolic reference can be made to a reference that does not exist. This is how a fresh, empty Git repository, with no branches, can be on branch master
even though branch master
does not yet exist. Hence, the branch to which HEAD
links, if HEAD
is not detached, may or may not actually exist—but there definitely will be a HEAD
.
A new, totally-empty repository, created by git init
, has a symbolic HEAD
that refers to the name master
.
(There is no way to set a HEAD reference to a branch that does not exist with the GitHub web interface, as far as I can tell. But a new repository is still created with HEAD
symbolically referring to master
.)
Remotes
Note that a remote is just a string in your own local Git repository. That is, you might create the name origin
to hold the url https://github.com/user/project.git
or ssh://git@bitbucket.com/user/project.git
or some such.
Nothing you do with your local repository will change anything in some other Git over on GitHub or Bitbucket, so any tweaks you make here have no effect. You need to cause the Git over at GitHub, or Bitbucket, or whatever other site actually hosts the server, to do something to its Git repository, before any change you make will actually have any effect.
(For GitHub, you simply log in to GitHub and manipulate your repositories using their web pages. This lets you do exactly those things they allow you to do, which is less than everything you could do if you could log in to their servers.)
Cloning: the other repository recommends a checkout
When you clone a repository using:
git clone [<options>] <url>
the options
allow you to specify, among other things:
What to call the other Git: the name of the remote. Use
-o xyzzy
to change the name from the defaultorigin
toxyzzy
, for instance.What branch name to check out in step six (see below). For instance,
git clone -b plugh
tells your Git togit checkout plugh
in step six.
If you leave out the -b
option, your Git asks their Git which branch they recommend. Your Git will, in general, then attempt to git checkout
this branch name in step six.
The method and details behind this recommendation have changed over time. In the distant past, your Git read their Git's HEAD
hash ID, if they supplied one, and guessed which branch name that meant. In modern Git, their Git can supply the literal text string read from the symbolic HEAD
reference. Your Git can choose to use this, or ignore it.
The git clone
command is shorthand for a six-step process:
Run
mkdir
(or whatever your computer's command may be) to create a new, empty directory, in which the new Git repository will be created. The remaining five steps run in this new empty directory.Run
git init
to create a Git repository (a.git
sub-directory within the new directory).Run
git remote add
to add a remote. The name of the remote will beorigin
unless you used the-o
option. The URL for the remote will be the URL you gave togit clone
.Run any extra
git config
commands required, e.g., from-c
options.Run
git fetch origin
(or whatever remote name you used), to obtain commits and populate your repository with remote-tracking names likeorigin/master
based on whatever branch names exist in the other repository.Run
git checkout
(pre-2.23) orgit switch -c
(Git 2.23 or later), to create a new branch and check out its commit.
The branch name used in step six is the one from your -b
option. Your Git will look at their branch (and tag!) names and if your -b
option matches one of their branch or tag names, will use that name. If the name is a tag name, your Git will go into detached HEAD mode on the appropriate commit.
If you did not use -b
, your Git will ask their Git which branch they recommend, as described above. If that is a name that works, your Git will create that name and check out that commit.
If both of those fail, your Git will fall back on the name master
. If that name also fails, your Git will tell you that step six failed: that you have a valid repository, and you got it all cloned, but there is no current branch and commit. It will be up to you to rectify this situation.
If the repository you clone has no master
Suppose you clone a repository from some URL, and that repository:
- does have commits; and
- does have branches—let's say, without loss of generality, that they have
br1
andbr2
, for instance; but - does not have a branch named
master
.
Suppose further that you, on your git clone
line, did not supply a -b
option. Then:
In step 5, your
git fetch
obtained theirbr1
andbr2
names and made yourorigin/br1
andorigin/br2
names. Since they have nomaster
, your Git did not make anorigin/master
.In step 6, you did not supply
-b
, so your Git asks their Git which branch they recommend.
If you have not taken any special action, the branch they'll recommend is the one whose symbolic name is in their HEAD
. If that symbolic name is master
, they will recommend their master
—which of course does not exist. Your Git will be puzzled by this recommendation (it doesn't work) and will use its own built in fallback: try master
. This too will not work and you will see what you saw.
Of course, if they do have a branch named master
, your step 5 will have created your origin/master
so your step 6 will be able to create your own master
based on their origin/master
, and all will be well.
If you have them change their symbolic name HEAD
to point to their br2
branch, the recommendation you will get in step 6 will be that your Git should create a branch named br2
based off their br2
, which is now (via step 5) your origin/br2
, and that will all work well too. But you need to reach into the server somehow and get them to change their recommendation.

- 448,244
- 59
- 642
- 775
-
I created the remote for instructional purposes, as per the video. It was created uisng git init --bare. It had no content until I pushed a branch to it. Unfortunately, the branch I pushed was not named master, and I did not name it as such on the remote. Then chaos ensued! – Anthony Mannucci May 31 '20 at 17:33
-
If you have direct access to the server on which the bare repository exists, simply enter the repository and run `git symbolic-ref HEAD refs/heads/branch` to change its recommended checkout to `branch`. Note that if you have a bare repository with a post-receive hook that runs `git --work-tree=
checkout – torek Jun 01 '20 at 00:27`, this post-receive script has the side effect of updating the `HEAD` in the bare repository, too. -
Note, too, that when you use `git push` from your own (non-bare) repository to the bare repository on a server, *you choose what branch name to ask the server to set* when you run `git push origin myname:theirname`. For instance if you have a branch named `br1` but you want the server Git to call it `br2`, you can `git push origin origin br1:br2`. This flexibility is built in to Git, but most people don't use it in practice: they create a branch named `master` locally, then push that to the bare server to have it create a branch named `master` in the server Git repository. – torek Jun 01 '20 at 00:31
-
Given that the bare server starts out recommending `master`, a client falls back on the default name `master`, and most people don't change any of this, that's why everyone has a `master`. When you go against this pattern by not having a `master`, people find that confusing. :-) – torek Jun 01 '20 at 00:32