TL;DR: Using Git has made our team much better by removing barriers to collaboration and code reviews. Those are the real Git benefits, not specific features like fast branches.
I heard about Git several times before starting 8th color, but was never convinced by the arguments that were presented to me. We started using Git from day one at 8th color, mostly because it “came with the package” - in the Ruby & Rails world, it seems that nary a developer is using SVN or even CVS.
18 months later, I finally feel confident enough to recommend it (on appropriate use cases) to my peers, mainly because, in my humble opinion, Git is very loudly but often very badly advertised. Here is a quick summary of the arguments I heard and discounted, and those I think are actually valid but too often overlooked
It come down to one thing: Git is not about speed or local commits or branches, Git is all about collaboration and code reviews.
What I heard about Git
My problem with Git advertising is that what I mostly heard were two things:
- “You can create branches very fast”
- “Git is distributed, you can commit locally”
Problem was, with some years of SVN experience under my belt, those points looked like what I call a solution looking for a problem. Fact is, I never had big problems creating branches using SVN/CVS - but I had my share of problems merging them. Even then: creating and merging branches were not part of my daily work.
The “commit locally” was equally flawed. I already had two states (uncommitted and committed); why did I need a third one (uncommitted, committed locally, committed remotely)? I did not work long without a connection anyway, and was used to short well defined commit already. Moreover, I was never comfortable with code sitting only on my machine, committed or not.
The problem here is that those two selling points are not benefits - they are mere features. You do not sell a product or tool on features - you sell the added value to your job. Those features are interesting, but not as such: they are interesting for what they bring to your development flow.
What I love
The big point about speed and easy branches (and, one should said, a sane branching model, where branches are not simply folders and conventions) is that it allows you to start using a significantly different collaboration model.
My typical SVN flow
We used the main branch (trunk) for the “long running development”. Once a release (V1.0) was scheduled, I created a tag once all features were in, and we started working on the next one (V2.0). Should a problem arise in production with the V1.0, we could then create a branch from the tag, fix any bug there, and release a V1.1 without impacting our V2.0 work (except to port any bug fix done, of course).
This worked pretty well, with almost no merges to do (the V1.1 branch was left to die, with work occurring on the main branch). Bugs had to be backported, of course, but we used to have reasonably short release cycles, which helped.
As for the various features that we were working on (in a team of 4-5 developers), I tried to find a way of splitting work that allowed most of the team relative freedom, with the rules that once the code was not making tests fail, it could be committed - even if not finished. We had our “conflict” moments, but it worked decently - and it still does - when I’m using SVN with other teams.
What Git allows: feature branches
The main benefit that Git unique feature brings is the possibility to use feature branches. By possibility, I do not mean the technical feasibility (you could theoretically make feature branches using SVN) but practical feasibility - if you are in a development team, your version control tool is, well, a tool, so it should work and allows you to create value.
Features branches are just that: they mean that each time that someone starts working on a feature or even a bug (depending of your level of orthodoxy), he/she creates a branch for that work from the main branch (typically named “master”). Several of them can be created at the same time, which will be frequent if you are making sprints - typically one per active developer, each on his own feature.
As branches are basically "free" (they are created instantly, which is logical once you understand how they are implemented), you can start working immediately, and commits can be pushed without problems - after all, you do not risk any other developers work, as you are “isolated”.
Once the feature is done and well tested, it can be merged into the master. You can then starts a new one - or use an additional step.
Removing barriers to code reviews and collaboration
The fact that each feature is on a separate branch make it much easier to do code review and generally to collaborate on code. Before merging back in the master, it is a good time and a good idea to ask for a review.
As the reviewer, you are probably busy in some code yourself. But with Git, if all your changes are committed (if they are not, there is still a way to save them temporarily), looking at a colleague code means just checking out his branch - again a very fast operation. You can then look at the code, run the tests or the code, and even commit changes if needed. Don't forget: “If you give a patch to a man, his code will be better today. If you discuss it with him, his code (and yours!) will be better for all his life.”
GitHub has actually made this process a feature named “Pull Request”, allowing for a conversation around the feature to take place in an easy way with a nice GUI.
Looking back at those Git features, the benefit is clear: it removes barrier to collaboration and code reviews, which are key to producing good software - and good developers.
From the trenches
Here are some recent, real life examples directly from our own three person team at 8th color.
- We produce new branches on a daily basis, and switch between them several times a day (for example to look at a colleague's code, then go back into our own).
- I did create a branch & the associated pull request for a modification of exactly two lines. This may look as overkill but even small patches deserve feedback and as it is free, why miss the opportunity?
- It happens that the review does not arrive immediately. In most situations, you can still create a new branch for the next feature, the merge can come afterward.
- The pull request & review process is “mandatory” (i.e. we decided that it was a good way),
meaning that we conduct peer review (once again: a review is not something a senior does on a junior code. It is something someone does on someone’s else code.) on a daily basis enhancing our code quality - and our team work.
- It is the reviewer job to merge the branch into the master. This is a "one second" job (using GitHub, it is actually one click), so why emphasize it? Because it means that the reviewer become co-owner (and co-responsible) for this code. If code you reviewed and allowed into the master ends up badly, you are as much guilty as the one that wrote it.
If this has convinced you to take a look at Git, some starters advice :
- Git works in a significantly different way than SVN or CVS. Not only that, you have to understand (at high level) the way it works, or it will come back and bite you, whether with a data loss (Git is rightly advertised as never losing any data, but possess commands or options that can actually remove some !) or just surprising situations (when switching branches with uncommitted changes, for example).
- Take a look at a Git Flow. Git low level commands allow for a lot of different possible workflows, meaning you have to pick one and stick to it - when are you creating branches, what do they means, how are they merged, etc. The model described in the link works pretty well for hundreds of team, and is probably a good starting point for yours too.
- Git UI is complex and inconsistent, but you need to use it. And I do not speak of any GUI here, just about the command line. A command line is a UI. Git command line UI sucks. Use it anyway.
- Stay where you are comfortable. Git has a lot, I mean A LOT of options and commands. You do not need everything to start. Actually 7 commands can get you really far
- Committing: add/commit: add basically add files that you changed to the next commit batch, and commit bundle them with your log message.
- Remoting: push/pull: push send your changes to the remote server, pull get the changes from the server back to you.
- Branching: branch/checkout/merge: branch create a new branch, checkout switch from one branch to another, merge merge the content of a branch inside the current one.
- Use and abuse pull requests (if you are using GitHub), or ask for review before each merge. It really makes a world of difference.
- Read about “merge vs rebase” if you want. No, don’t. On some mornings you can see advocates of both taking the sweet spots in Hacker News' home page for saying exactly the opposite. Be warned: Here Be Dragons. My own advice on this subject is a cup of tea and a good spot on the sofa. Technological church wars are so fun to watch.
I hope you’ll find the journey as frustrating and the arrival as beneficial as I did.