2009年10月1日星期四

Publishing git repositories

Despite a distributed version control system by design, git can just as well be used in a centralised fashion. When a user clones a git repository, git sets up the local clone such that it is aware of its origin. Let’s have a look at the relevant lines in .git/config:


[remote "origin"]
url = ssh://server/path/to/repo.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master


The “remote” stanza defines a remote repository with the nickname “origin”. If the user calls git fetch without arguments, it will download all remote branches (refs/heads/*) and store those as remote branches with the origin/ prefix. Thus, the branch “big-fat-feature” in refs/heads/big-fat-feature on the other side becomes the remote branch “origin/big-fat-feature” (refs/remotes/origin/big-fat-feature).

The “branch” stanza informs git about the default source for merges when the “master” branch is current. If the local “master” branch is checked out and the user calls git pull without arguments, it instructs git to fetch all branches (see above), then merge the remote “master” branch (refs/heads/master) into the current branch.

I started a new project in git today and decided to go public after I had already made a few commits and created a number of branches.

So I set out to learn a bit more about git internals and came up with two ways to publish the repository such that my local repository would also know about the remote side as if it had been cloned from the start. The documentation didn’t leave me satisfied, so I had to try it all out.

Being new to git, my first thought was to push/publish my repository to a public location, and so I did:


### assuming ssh://server/remote.git resolves to an empty, bare git repo
### and that we are chdir()'d to the local repository:
$ git push --all ssh://server/remote.git
$ git remote add origin ssh://server/remote.git
$ git config branch.master.remote origin
$ git config branch.master.merge refs/heads/master
$ git fetch
$ git merge master
$ git branch
big-fat-feature
* master
ponies
$ git branch -r
origin/big-fat-feature
origin/master
origin/ponies


Another method then dawned on me, but it’s not necessarily better. Instead of pushing, let’s copy a clone over and then clone that once more:


$ git config core.bare true
$ scp -r .git server:/remote.git
$ mv `pwd` `pwd`/../OLD
$ cd ..
$ git clone ssh://server/remote.git
$ cd remote
$ git branch
big-fat-feature
* master
ponies
$ git branch -r
origin/HEAD
origin/big-fat-feature
origin/master
origin/ponies


This does almost the same, except for that origin/HEAD branch, but that’s just a local symbolic ref (a “symlink”) and can just be removed, really:


$ rm .git/refs/remotes/origin/HEAD
$ git branch -r
origin/big-fat-feature
origin/master
origin/ponies


Now the only thing left is setting core.sharedRepository on the remote side to let git know how to handle the Unix permissions. And that’s it.

http://madduck.net/blog/2007.07.11:publishing-git-repositories/

没有评论:

发表评论