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.
NP: Antimatter: Lights Out

