Software Development And Revistion Control

05 September 2012
Update: 08-09-2019 this post is pretty old. I stopped using the methodology described below. I would advice to use GitHub flow now.

I was asked by Fonk Mobile to write about my experiences with revision control, in this blog you can read what I wrote for them:

I think it’s safe to say that revision control is a must have if you are a programmer. There are some different tools available. Most known revision control systems are Git and SVN.

This big difference between SVN and Git is that SVN has a centralized server, with Git everything is decentralized. In my opinion Git is much nicer if you hack and prototype a lot. Mostly because it’s so easy to create a Git repository I even use it for quick mockups and prototypes. There are a lot of GUI’s available for using Git but I strongly recommend using the command line. It gives you much more understanding and control over what you are doing.

Wikipedia page for Git

In software development, Git is a distributed revision control and source code management (SCM) system with an emphasis on speed. Git was initially designed and developed by Linus Torvalds for Linux kernel development; it has since been adopted by many other projects. Every Git working directory is a full-fledged repository with complete history and full revision tracking capabilities, not dependent on network access or a central server. Git is free software distributed under the terms of the GNU General Public License version 2.

Sharing your work

Git is designed for sharing, every Git repository you have on your local machine is a copy of the complete history of the project. Because you store everything locally you can switch between versions super fast. Every Git clone can be a server.

For example, if you want to start working on a Github project you can do this:

$ git clone https://github.com/h5bp/html5-boilerplate.git
# Cloning into html5-boilerplate...
# remote: Counting objects: 4713, done.
# remote: Compressing objects: 100% (2090/2090), done.
# remote: Total 4713 (delta 2681), reused 4379 (delta 2500)
# Receiving objects: 100% (4713/4713), 9.20 MiB | 100 KiB/s, done.
# Resolving deltas: 100% (2681/2681), done.

This will download the whole project and it’s history. If you look at the commits you see this project contains almost 1200 commits.

To push something to a server you must have access to the repository, if you have access it’s as easy as executing this command:

# master is the branch you want to push
# origin is the name of your server
$ git push master origin

Branches

A branch is basically a new experiment or feature you are trying with your code.

When you are working on something new it’s a good idea to start a new branch, when you are not happy with the outcome it’s really easy to throw the new part away. Creating a branch in Git is really fast and easy. On the command line you enter these commands:

# create and checkout the a new branch
$ git branch new-branch-name
$ git checkout new-branch-name

To remove a branch you add the -d to the branch command

$ git branch -d new-branch-name

As you can see this requires some typing in the command line. This is where Git Flow comes in, Git Flow makes the whole branching simpler.

Git Flow

Vincent Driessen (@nvie) wrote a blog post in January 2010, where he described a good branching model. I highly recommend you reading this post. After this post a lot of people started using his model for projects. And when he finished his blog post he started writing a plugin for Git to enforce his way of working. This plugin is called Git Flow and is pretty easy to install, you can look at the manual to get started.

Starting with Git Flow

$ git flow init
# No branches exist yet. Base branches must be created now.
# Branch name for production releases: [master]
# Branch name for "next release" development: [develop]

# How to name your supporting branch prefixes?
# Feature branches? [feature/]
# Release branches? [release/]
# Hotfix branches? [hotfix/]
# Support branches? [support/]
# Version tag prefix? []

Git Flow asks what names you want for your branches, I suggest you stick with the defaults.

The branches within the Git Flow paradigm

Master

The master branch is always releasable and running on the main production server. This branch is sacred, NEVER commit straight onto this branch!

Develop

This is the branch where everybody develops from. If you have a really small change you can use develop. But if you start on something that takes more than a minute you should use feature branches

Feature branches

From the Git Flow blog post:

Feature branches (or sometimes called topic branches) are used to develop new features for the upcoming or a distant future release. When starting development of a feature, the target release in which this feature will be incorporated may well be unknown at that point. The essence of a feature branch is that it exists as long as the feature is in development, but will eventually be merged back into develop (to definitely add the new feature to the upcoming release) or discarded (in case of a disappointing experiment).

When you installed the git flow plugin it’s really easy to start a new feature;

$ git flow feature start feature-name
#
# Switched to a new branch 'feature/feature-name'
#
# Summary of actions:
# - A new branch 'feature/feature-name' was created, based on 'develop'
# - You are now on branch 'feature/feature-name'
#
# Now, start committing on your feature. When done, use:
#
#      git flow feature finish feature-name

As you can see the plugin gives a good explanation what to do next.

Below is a visual representation of a feature branch, you also see what a feature is if you don’t create a branch for it (on the right)

To finish a feature you enter this command on the command line

$ git flow feature finish feature-name

Release branch

When you are ready to release a new version to your production server you create a new release branch (for version v1.1.1).

$ git flow release start v1.1.1
# Switched to a new branch 'release/v1.1.1'
#
# Summary of actions:
# - A new branch 'release/v1.1.1' was created, based on 'develop'
# - You are now on branch 'release/v1.1.1'
#
# Follow-up actions:
# - Bump the version number now!
# - Start committing last-minute fixes in preparing your release
# - When done, run:
#
#   git flow release finish 'v1.1.1'

This creates an additional branch where you can do the last things that need to be done before it gets deployed. In the console output above Git Flow gives some hints on what you should do in this branch; Bump the version number and do some last-minute fixes.

When you are done with this you should enter this command:

$ git flow release finish 'v1.1.1'

Hotfix branches

Hotfix branches are a bit weird when you start using Git Flow, they diverge from the master and not from develop is the first gotcha.

As the Git Flow blog post writes:

Hotfix branches are very much like release branches in that they are also meant to prepare for a new production release, albeit unplanned. They arise from the necessity to act immediately upon an undesired state of a live production version. When a critical bug in a production version must be resolved immediately, a hotfix branch may be branched off from the corresponding tag on the master branch that marks the production version.

The essence is that work of team members (on the develop branch) can continue, while another person is preparing a quick production fix.

To start a new hotfix execute this command on the command line:

$ git flow hotfix start hotfix-description                                                             master [cb1d985]
# Switched to a new branch 'hotfix/hotfix-description'
#
# Summary of actions:
# - A new branch 'hotfix/hotfix-description' was created, based on 'master'
# - You are now on branch 'hotfix/hotfix-description'
#
# Follow-up actions:
# - Bump the version number now!
# - Start committing your hot fixes
# - When done, run:
#
# git flow hotfix finish 'hotfix-description'

When you are done with your hotfix you can execute

$ git flow hotfix finish 'hotfix-description'

Which shows an output similar to:

# Summary of actions:
# - Latest objects have been fetched from 'origin'
# - Hotfix branch has been merged into 'master'
# - The hotfix was tagged 'hotfix-description'
# - Hotfix branch has been back-merged into 'develop'
# - Hotfix branch 'hotfix/hotfix-description' has been deleted

Conclusion

At first Git and Git Flow seem pretty complex, but I have learned that once you know the basic commands it’s quite easy to work with Git and Git Flow. There are also a lot of good references (see end of this article). As we saw in the example code a lot is explained in the console output of Git Flow.

For bigger projects; use continuous integration

When the whole team works within this structure it is a good idea to hook your code repository to a continuous integration server, or build server, this server should push changes on the master branch to production automatically. If you work on a web project it should upload it to your server. For iOS development it should compile the product.

And because the master branch is always production ready it’s perfectly fine to deploy. The develop branch could be pushed to a staging server, if you have one. On this server everybody can test the upcoming release before it goes to production.

What about those version numbers?

For the last year I am using a scheme in my version numbers, this method is called Semantic Versioning and is described on this website. It describes how the numbers in a version number should be used. When do you add an extra number (1.1.1) and when do you create a new dot release (1.2.0)

I call this system “Semantic Versioning.” Under this scheme, version numbers and the way they change convey meaning about the underlying code and what has been modified from one version to the next.

An important question is, when do you release a version 1.0, Semantic Versioning gives an answer:

If your software is being used in production, it should probably already be 1.0.0. If you have a stable API on which users have come to depend, you should be 1.0.0. If you’re worrying a lot about backwards compatibility, you should probably already be 1.0.0.

References