By Nathan L. Walls

  • Icy Creek/Raleigh
  • Bare Tree, Frozen Lake/Raleigh
  • Branching Shadows/Raleigh
  • Silhouetted Oak/Raleigh

Git cloning and branch heads

Last week at work, I was trying to diagnose apparent trouble with a Git repository. Whenever the infrequently updated repository was cloned, we would end up in a different branch than our devel branch. Not knowing if there was a problem in the remote bare repository, I dug around refs/heads and HEAD on both the remote repository and in a fresh local clone. Not seeing any apparent trouble, I Googled.

I came across the following mailing list post that explained my trouble:

… the git protocol does not expose which branch HEAD points to, only which commit. So if two branches point to the same commit, git just takes the first branch and points the local HEAD to that.

How we ended up in that situation is like this:

  • Starting with an existing repository, create a branch off of master or whatever other branch you treat as your default HEAD
    • NB: We use devel as a historical artifact
  • Publish the new branch to the remote origin
  • Clone the repository somewhere else and examine the new clone. There’s a good chance the new repo will be using the new branch instead of master

I created a GitHub repository to demonstrate (although there’s no guarantee you’ll get the new branch on clone).

$ git clone https://github.com/base10/branch-head-examples

(add files)

$ git push
$ git branch feature
$ git push -u origin feature

Now, I’m going to look at a fresh clone:

$ git clone git://github.com/base10/branch-head-examples.git clone-example
$ ls clone-example/.git/refs/heads

So, I didn’t get feature. If however, in your clone, you saw this …

$ ls clone-example/.git/refs/heads

… you would just need to do this:

$ cd clone-example
$ git checkout master
Branch feature set up to track remote branch master from origin.
Switched to a new branch 'master'

Now, diff the refs/heads files:

$ diff .git/refs/heads/master .git/refs/heads/feature

Getting an unexpected branch from a repository in this state isn’t harmful. It is a little disconcerting if you’re looking at a repository you established, but don’t work with frequently. I suspect this case is more likely to come up under the following circumstances:

  • You don’t have a master branch at all (which might be true if you’ve converted a Subversion repository) or master is a dead branch
  • You have a mainline of development and create a release branch from the mainline of development
  • The repository, with all branches, is pushed
  • The repository is later cloned, with no further changes.