[2013-05-31] Git for multiple people
**Update: Just over a week later, I'm no longer sure I agree at all with this article anymore. Maybe go read the Distributed Workflows chapter of the Pro Git book instead. I've left the original article below, with all its warts, for archival purposes.
So, I've been using Git for more than a year now, but it's mostly been just for myself -- I keep a GitHub account and so I use Git to keep that up to date with the latest things I've been up to.
But until recently, I haven't really had to do Git with multiple people, and I haven't really known the right way to handle that. I think I may have twigged onto the right idea, though:
Don't: use Git like SVN
At my workplace, I've got some folks who are using Git to manage revision control for their (fairly extensive) project. The problem they keep running into is that none of them really know how to use it (in the sense of knowing how git thinks, for certain values of "think"), and they are unwilling or unable to take the time to learn how it actually works. So they've been using Git as if it were Subversion: everyone pushes their commits to master, everyone deals with merge conflicts, and everyone complains that Git is "so bloody hard to use" or "so annoying".
To some extent, I shouldn't be too sympathetic (programmer, know thy tools!), but I do feel some understanding of what it's like to be dumped into an unfamiliar system and have to use it as best you can because the work must be done immediately, if not sooner.
But it's pretty obvious, regardless, that using Git as if it were SVN introduces a lot of pain into the process of getting your code to where everyone can see and use it, so there must be a better way. For the last couple of months, I've been pondering this problem.
Do: learn to love branches
One of Git's strengths (which it shares with other DVCSes) is almost seamless branching. I've contributed a little to Cataclysm: Dark Days Ahead, and watched how they handle this kind of problem. You know what they do a lot? They branch. A lot. All the time.
Every single patch made to the official master branch of that repository comes out of a pull request, which means it's coming out of someone's branch built for one specific thing. Some branches have a bugfix (and just the one bugfix!), others have a small (or not so small) feature addition; practically all of them came off the master at some point and never went back to it.
Do: have someone responsible for merging
Here's the magic trick: make someone responsible for merging patches into master. Make sure it's someone who actually learns the ins and outs of Git, and how to rewrite history (if necessary), and how to resolve merge conflicts (if they ever happen), and never let anyone other than this person merge things into origin/master.
Because of how well Git handles branches, most of the time the only thing the person in charge of merging has to do is say git merge branch-name
and it will "just work". Whenever it doesn't, the person resolving the merge is someone who knows Git, and can mix things up if necessary so that the resulting history is clear.
Try: not keeping branches around if they've been merged into master
For everyone, in all cases, git pull origin master
should be a fast-forward. Nobody should have to deal with a merge conflict for pulling the latest master -- if that ever happens, something went wrong (perhaps they committed something into their local master?) and that something should itself be fully fixed before they go any further.
In most cases, branches should merge into master without conflicts, even if they're based on an old revision of master. You shouldn't be worried about "being out of date" with the original master -- unless you're trying to do something that relies on a behavior (class, method, whatever) that only exists in the latest master, don't pay the slightest attention to that. Only if you really need something from the current master should you merge it into your work-in-progress branch (and take a look at git cherry-pick
, it might be useful in some cases).
Remember: Fast-forwards are awesome
The fewer people who have to deal with merge conflicts, the better off you will be. Ideally, you only ever want the repository maintainer to have those problems -- everyone else should be seeing fast-forwards instead.
As you get more people with Git experience (or who are willing to learn), feel free to add them to the group of maintainers, if you want, but make sure they know their stuff before you let them make a mess in your master. Pulling from origin/master
into your local master
should always be a fast-forward.
However: remember I'm not really a Git guru
This is just the latest set of recommendations and conclusions I've reached, after watching how those around me use Git. I don't claim that it's the best way, and it sure as hell isn't the only way, but this seems to work well, especially if you have someone who can use Git well (they don't have to be a guru, just be familiar with it).
Disagree? Have a better idea? I'm afraid I still haven't gotten around to adding comments to this place, so you'll have to contact me and I'll take care to post it for you.