What determines default branch after "git clone"?

GitGit Clone

Git Problem Overview


My understanding is that the default branch of a cloned repository is to be whatever HEAD points to in the repo being cloned.

I now have a case where this is not true. My understanding is obviously flawed, so what does determine the default checkout branch when cloning a (bare) repo?

The last commit on that repo was a merge between the branch referenced in the bare repo's HEAD into the branch I'm getting as the checkout branch in the clone.

Running git remote show origin returns:

Fetch URL: ...
Push  URL: ...
HEAD branch (remote HEAD is ambiguous, may be one of the following):
  <bad-branch>
  live
Remote branches:
  ...

Bare repo uses Git version 1.8.2.1, client uses 1.7.12.4, transport is SSH.

Maybe the answer is actually this one here. This answer confirms it. If there is a choice of symbolic refs all pointing to the same revision as HEAD, the client will guess which branch to use.

Git Solutions


Solution 1 - Git

Beginning with Git 1.8.5, the server will send the actual branch name that HEAD points to, in the "symref" capability. If you have both a client and server newer than Git 1.8.5, it will update HEAD correctly.

Prior to that, the client will guess what HEAD may have pointed to by comparing the object ID that HEAD (ultimately) points to with all the object IDs of all the branches. It prefers a branch named refs/heads/master: if both HEAD and master point to the same object ID, then clone will set the default branch in the new repository to master.

Otherwise, the first branch with a matching OID (when the branches are sorted alphanumerically) will be the default branch. If no branches have matching OIDs, then HEAD will be set directly to the object ID (ie, a detached HEAD).

Solution 2 - Git

It is actually what HEAD points to. Use git symbolic-ref HEAD refs/heads/mybranch for setting HEAD. (source: http://feeding.cloud.geek.nz/posts/setting-default-git-branch-in-bare/ )

Solution 3 - Git

A bare repo has a HEAD, too. That's what you get when you clone it.

From the git clone documentation:

> Clones a repository into a newly created directory, creates remote-tracking branches for each branch in the cloned repository (visible using git branch -r), and creates and checks out an initial branch that is forked from the cloned repository's currently active branch.

The bit about "currently active branch" is referring to the remote's HEAD revision.

If you want different behaviour, you can use --branch or -b:

>--branch <name>
>-b <name>
>Instead of pointing the newly created HEAD to the branch pointed to by the cloned repository’s HEAD, point to <name> branch instead. In a non-bare repository, this is the branch that will be checked out. --branch can also take tags and detaches the HEAD at that commit in the resulting repository.

Solution 4 - Git

It's origin/HEAD. However if you want the name like 'origin/master' you'd have to parse the file like this

cat .git/refs/remotes/origin/HEAD | awk '{ print $2 }'

Solution 5 - Git

If want to manually check out the default branch of the origin remote, this should work reliably:

git switch $(cat $(git rev-parse --git-dir)/refs/remotes/origin/HEAD | cut -d'/' -f4)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChristian GoetzeView Question on Stackoverflow
Solution 1 - GitEdward ThomsonView Answer on Stackoverflow
Solution 2 - GitValentin LorentzView Answer on Stackoverflow
Solution 3 - GitCarl NorumView Answer on Stackoverflow
Solution 4 - GitArchimedes TrajanoView Answer on Stackoverflow
Solution 5 - GitxerufView Answer on Stackoverflow