Wednesday, August 26, 2009

Using git with Small Teams

For the time being, Gents with Beards is a small operation. As a result, we want simple solutions to our problems. One of the first problems we addressed was source control, and the solution we decided upon was git. For those who don't know, git is a source control system developed by Linus Torvalds to store the Linux kernel's source code. git is a good choice for distributed teams, but it is also an excellent choice for small teams who all sit in the same room. This post will describe our git setup and workflow. Before going further, however, I would be remiss if I didn't mention gitosis. I have not used it personally, but have heard many good things about it. You should definitely consider it if you plan to use git.

We use ssh as the transmission protocol of choice. We all use Macs, so it was possible to set up our git remotes with bonjour hostnames: cathode.local, macteague.local, and rivendell.local. Incidentally, I have set up user accounts for both of the other gents, but this has unintended ramifications. MacOS permissions are very permissive in the default configuration - but that's for another post. I also set their login shell to git-shell.

There is no central server; instead, we fetch directly from each other. As a result, there is no single authority for the one true version of the code. While that sounds scary, in practice it hasn't been a problem. When I want to implement a feature, I usually create a new branch. I make my changes in that branch, and then merge it back into my master branch. I then tell everybody else that they should fetch my changes. They will pull my master into their master (which more often than not turns into a simple fast forward). Thus, a few minutes after I finish a feature, it is shared with the other team members.

Occasionally, two people will complete features around the same time. When this happens, they each have master branches that have diverged. In this case, when we try to merge the different master branches together, a fast forward won't suffice. In this case, we end up with one additional merge to combine the masters. This hasn't really been a problem for us.

To get changes from others, we use git fetch. For example, to get changes from Marc, I would use:

git fetch marc
One could also use:
git fetch marc master
This would update my remotes/marc/master to point to his master commit, and would also fetch any necessary objects. However, when I fetch a particular branch, I only get updates to that branch. When you fetch without specifying a branch name, git will actually create or update entries in remotes/marc for every branch marc has. In a large team, this would be a terrible idea, but it works very well for us. If I decide that I want to work on the same feature, I can use:
git branch feature-branch-name marc/feature-branch-name
Now I have a local branch with the same name as Marc's branch. We can each make changes, fetch them from one machine to the other, merge the changes as necessary, and generally collaborate with ease. We will occasionally use git pull, but I like to separate fetching from merging.

We tag releases, and the tags end up getting shared with everybody when they fetch changes.

Something interesting about our workflow is that we never push changes. We will want to introduce a build server at some point, at which time we will need to have an authoritative copy of the code. Then, pushing will become more important.

One thing that disappointed me is that git doesn't seem to work as well when the machines aren't on the same network. At home, my laptop isn't internet routable, and neither are any of the other Gents' laptops. So, if I work on something at home, it's hard for me to send to the others. I could use patches, but that will cause history to be different between me and the others. I want to investigate git-bundle, which may do what I want.

No comments:

Post a Comment