206
votes

I have a bare repository that's used as the central store for my project. All the developers do git clone <repo> to share with it. When they do the clone, they get a checkout of the master branch (unless they do git clone -n) because repo.git/HEAD contains ref: refs/heads/master, making this the Active Branch.

The question is, how do I change the Active Branch properly? I could simply hack the repo.git/HEAD file directly, but that seems nasty and, well, hacky.

I tried doing git checkout <otherbranch> in the repo .git directory, but that failed because I wasn't in a work tree.

I tried git update-ref HEAD refs/heads/otherbranch but that just updated refs/heads/master to be the same as refs/heads/otherbranch (okay, I did that one in a dummy repository, not my production one!)

I tried git update-ref --no-deref HEAD refs/heads/otherbranch and that almost worked. It updated the HEAD file, but it set it to the SHA1 of the commit pointed to by refs/heads/otherbranch.

I'm testing with git version 1.7.0.2.msysgit.0.

I'm guessing there's no way to do this through git push, as allowing all and sundry to change your default branch seems a bit unsafe (!), but surely there's a better way to do it in the repo .git directory than directly hacking the HEAD file.

6
IMO you're just fundamentally trying to do The Wrong Thing here. If you want the default branch to be something other than master, then that branch needs to be the master. Alternatively, use two different repositories.Nicholas Knight
How is this fundamentally trying to do the wrong thing here? A bare repository supports multiple branches. I use a bare repository as back-up to my local repository, and as such mirror the branches. I have a master on both and a development branch on both. If I want to see the log of the development branch on the bare repository, I have to hack files - seems like git is fundamentally wrong here with regard to bare repository support.Cthutu
@NicholasKnight IMHO you're fundamentally wrong here. There is nothing special about "master" as a branch name, it's just a default. In the respositories that maintain we don't have a master branch, as "master" is not meaningful to the company. Whenever we do a release we create a new maintenance branch with the new release number, and assign that as the active branch.Spacemoose
@NicholasKnight While I appreciate where you're coming from, this is the first SO Q/A that's told me how to switch to master! I had my initial repo on a feature branch when I made my bare clone, and subsequent clones from that bare repo were defaulting to that branch instead of master.Warbo
Wow - this question just runs and runs - it's my number 1 reputation point scorer! The thing about "master" is that it's just a name, and if it doesn't make sense for your organisation, team, project, phase, whatever, then choose something that IS appropriate so that when you collaborators clone your repo they immediately switch to the branch that you, as Configuration Manager, want them to be on. I used to work with ClearCase (bletch!) so your choices were "main", "main" or "main". Yuk.kbro

6 Answers

298
votes

If you have access to the remote bare repo, this article suggests:

git symbolic-ref HEAD refs/heads/mybranch

Which will update the HEAD file in your repository so that it contains:

ref: refs/heads/mybranch

as documented in the git-symbolic-ref


If you don't have access to the remote repo, see my previous answer.


Remember that a command like git remote set-head:

  • doesn't change the default branch of the remote repo.
    It only changes a remote tracking branch stored in your local repo as refs/remotes/<name>/HEAD

  • doesn't change HEAD itself (again, only refs/remotes/<name>/HEAD), hence the need for git symbolic-ref.

So git remote set-head is not the answer here.
git symbolic-ref HEAD is, if you have direct access to the remote repo.

4
votes

To change the branch you need to change HEAD reference to the branch you want to use.

First list all the references in the bare repository by doing

$find ref

Then find the reference for your branch, the format will be as follows refs/heads/<my_branch>. So next step is to check current reference, just type:

$git symbolic-ref HEAD

so you know which is the current branch then update it as needed.

$git symbolic-ref HEAD refs/heads/<my_branch>

That's it. Enjoy.

2
votes

How to change the Active Branch properly ?

  • status: git checkout in the repo .git directory returns fatal: This operation must be run in a work tree

  • tips: just add the --work-tree argument

detailed example : assumptions: bare git on remote server:

~/bare_git_repository.git detached work tree: /var/www/myappremote

on local server: create branch version.1.7 (our otherbranch)

git branch version.1.7

git push origin version.1.7

on the remote server with git bare repo:

$ cd ~/bare_git_repository.git

$ git branch

  • master
    version.1.7

As stated,following command

git checkout version.1.7

return

fatal: This operation must be run in a work tree

Using the following command

git --work-tree=/var/www/myappremote checkout version.1.7

successfully change the Active Branch propely

$ git branch

master

  • version.1.7

check the results with the following

ll /var/www/myappremote

hope it will help

-1
votes

Also, if you don't have access to the bare repository, by doing a git remote set-head and you are done

See this previous response

-3
votes

I also have a bare repo on our server and was able to successfully retrieve files using

git clone //server/repo/directory -b branch_name

into a new local repository even though the manpage says this is only for non-bare repositories.

-4
votes

I compared two directories before and after applying

git symbolic-ref HEAD refs/heads/mybranch

and it appears that only repo.git/HEAD file was changed so probably it is quite safe just to "hack" the file.