views:

1757

answers:

3

Short version: How do I set a Git remote's HEAD ref to point to something besides "master"?

My project has a policy not to use a "master" branch (all branches are to have meaningful names). Furthermore, the canonical master repository is only accessible via ssh://, with no shell access (like GitHub or Unfuddle).

My problem is that the remote repository still has a HEAD reference to refs/heads/master, but I need it to point to a different branch. This is causing two problems:

  1. When cloning the repo, there this, warning: remote HEAD refers to nonexistent ref, unable to checkout. That's confusing and inconvenient.
  2. The web-based code browser depends on HEAD as a basis for browsing the tree. I need HEAD to point to a valid branch, then.
+6  A: 

There was almost the same question on GitHub a year ago.

The idea was to rename the master branch:

git branch -m master development
git branch -m published master
git push origin master

Making master have what you want people to use, and do all other work in branches.

(a "git-symbolic-ref HEAD refs/head/published" would not be propagated to the remote repo)


As said in this thread: (emphasis mine)

"git clone" creates only a single local branch.
To do that, it looks at the HEAD ref of the remote repo, and creates a local branch with the same name as the remote branch referenced by it.

So to wrap that up, you have repo A and clone it:

  • HEAD references refs/heads/master and that exists
    -> you get a local branch called master, starting from origin/master

  • HEAD references refs/heads/anotherBranch and that exists
    -> you get a local branch called anotherBranch, starting from origin/anotherBranch

  • HEAD references refs/heads/master and that doesn't exist
    -> "git clone" complains

Not sure if there's any way to directly modify the HEAD ref in a repo.

(which is the all point of your question, I know ;) )


Maybe the only way would be a "publication for the poor", where you:

 $ git-symbolic-ref HEAD refs/head/published
 $ git-update-server-info
 $ rsync -az .git/* server:/local_path_to/git/myRepo.git/

But that would involve right access to the server, which is not always possible.

VonC
Thanks, VonC. I read that before posting here. But as you can see, a branch called "master" is unwelcome in this project for technical and policy reasons.
jhs
You could then enforce that policy by disallowing any update on master branch through a pre-commit hook.
VonC
Yes, if it turns out that there is no way to do what I want then I will do exactly that and accept your answer. Thanks for following up!
jhs
Thanks for the update. For the moment, I used the "no-common-ancestor" trick to make a master branch with only one commit. (I.e.: git branch -D master; echo ref: refs/heads/master > .git/HEAD; rm *). Then I just touched a file called GO_AWAY, and commit message explains the situation. That will work for now. I may check through the source and track down where the receiving side sets HEAD for a final answer.
jhs
+2  A: 

There was already basically the same question "create a git symbolic ref in remote repository", which received no universal answer, but there was there a specific answer for Github -- that might be useful for those reading this page and thinking about Github.

(Unfortunatley, as for me, I care about gitorious, not Github.)

imz
+2  A: 

You can create a detached master branch using only porcelain Git commands:

git init
touch GO_AWAY
git add GO_AWAY
git commit -m "GO AWAY - this branch is detached from reality"

That gives us a master branch with a rude message (you may want to be more polite). Now we create our "real" branch (let's call it trunk in honour of SVN) and divorce it from master:

git checkout -b trunk
git rm GO_AWAY
git commit --amend --allow-empty -m "initial commit on detached trunk"

Hey, presto! gitk --all will show master and trunk with no link between them.

The "magic" here is that --amend causes git commit to create a new commit with the same parent as the current HEAD, then make HEAD point to it. But the current HEAD doesn't have a parent as it's the initial commit in the repository, so the new HEAD doesn't get one either, making them detached from each other.

The old HEAD commit doesn't get deleted by git-gc because refs/heads/master still points to it.

The --allow-empty flag is only needed because we're committing an empty tree. If there were some git add's after the git rm then it wouldn't be necessary.

In truth, you can create a detached branch at any time by branching the initial commit in the repository, deleting its tree, adding your detached tree, then doing git commit --amend.

I know this doesn't answer the question of how to modify the default branch on the remote repository, but it gives a clean answer on how to create a detached branch.

kbro