Using git as a central repository

git

I have set up git for my own use–so I can access a project from 'anywhere', and keep version safety if I happen to be working on part X over here, and part Y over here, and can merge if necessary.

However, only one of my development machines has a static IP. My brain is stuck in CVS mode, so I tried to set up git to have that machine be the 'central' server, which all others pull from.

This sort of works. I have a bunch of machines A-C which do a git-pull from the 'master' M. They do git pushes to send the data back.

The problem comes if I do development on the master. First, I can't figure out how to get the central repo to provide the latest version without doing

git reset --hard HEAD

which seems a bit excessive. And if I do development on the central machine before resetting, I'm not sure how to merge it with changes that have already been pushed up.

Something about my mental model is way off. Help?

Best Answer

You want your central repository to be bare. Say the machine it lives on is named static:

$ ssh static git init --bare /git/myproject.git

This bare repository is a central rendezvous point: it's for pushing to and pulling from, not development.

Do your development on clones of the central repository:

$ cd ~/src
$ git clone static:/git/myproject.git

Even if you're on static, work in a clone:

$ git clone /git/myproject.git

Although you're the only one working on this repository, get in the habit of doing your work on what the git documentation calls topic branches. An immediate benefit of this is that it keeps a clean master, that is you can always pull from your central master branch into your current local repository's master with no merging.

For example:

$ git checkout -b fix-bug-in-foo
$ hack
$ git add file.c file.h
$ git commit -m "Fix ..."

That may not seem like a big deal, but it gives you the freedom to leave the project as represented on that branch in a partially cooked state, or if your cool idea turns out to be a flop, you can easily throw away that branch without breaking anything else in your project that's already working on other branches. Infinite free mulligans!

Maybe you go home that night and added a new feature. The next morning, you

$ git checkout master
$ git pull

to update your local master to reflect what's in the central repository.

But now say you've fixed the foo bug and are ready to include it in your master branch. First you want to integrate it with the changes from last night:

$ git checkout fix-bug-in-foo
$ git rebase master

The rebase command makes your repository look as though you fixed the foo bug on top of last night's new feature. (This is sort of like svn update, but more flexible and powerful.)

Now to get it into your central master:

$ git checkout master
$ git merge fix-bug-in-foo
$ git push origin master

We've been treating master as special, but that's only conventional. You can share work on different branches of different repositories through the git repository on static just as easily.