Software branching strategies: A git overview | Part 1: gitworkflows

We will start by presenting a working example, which will be used as a basis to illustrate the various git branching models from a practical point of view. In the first part of the serios, we’ll detail the rules and practices of the gitworkflows branching model. Towards the end of the series we will outline several common approaches that have emerged as best practices in recent years.

An important note to make is that we will approach the branching strategies from several distinct perspectives. The most frequently used is the developer one, and sometimes the only one considered. But we also need to place ourselves in the bug hunter shoes, to account for the different midset needed to identify when a certain change has been introduced. Moving forward from the people creating / changing the software, we will account for the packagist role, responsible for assembling software into the package that will be deployed in a specific environment.

Working example: AcmeGreen

Let’s assume we are working on a new greenfield project, named AcmeGreen. Our internal project management tool is Jira, and the project codename is AG.

When we first created the repository, we started with the master branch. Each of our initial features received their own branch. To easily find them, our team has reused a naming convention they previously used, to use a <project>-<4DigitsTaskNumber>-<details> name them after the Jira tasks they are attached to. So in our system there are currently some extremely recent branches, all originating from master:

  • AG-0001-initial-setup prepares the project codebase
  • AG-0002-use-cases that the BA and product owner are working on to define the core functionality in the form of use cases

Strategy: gitworkflows

The manual page for gitworkflows1 presents a set of rules and tries to motivate each of them. Let’s see what they are, and use our working example as illustration.

  • preparation of the upcoming maintenance release is done on maint
  • master holds the work in progress that is preparing the future release
  • next is a stability brach for testing items that will be promoted to master
  • throw-away integration brach pu, which stands for “proposed updates”

Rule: Topic Branches

Make a side branch for every topic (feature, bugfix, …).
Fork it off at the oldest integration branch that you will eventually want to merge it into.

To prepare the ground for our team, we will open a AG-0001-initial-setup branch off master. This is the place to add initial gitignore rules, define the basic coding standards, etc.

$ git checkout master # start from the master branch
$ git checkout -b origin AG-0001-initial-setup

# [...] relevant commits in between

$ git push origin AG-0001-initial-setup # publish our work for the teammates benefit

Rule: Merge Upwards

Always commit your fixes to the oldest supported branch that require them.
Then (periodically) merge the integration branches upwards into each other.

The AG-0001-initial-setup is a few commits ahead. You can have a quicklook at them by executing

$ git log --pretty=oneline

9cf571c1c1225a5fecf61c43981048fb16193860 setup gitignore rules
3c1fef41a9ca5d1b24f767404f9bfd52affab90c naming convention for short-lived branches
0c1fe345edbebde03f217e7c67d5f67626f2ca7b explain long-term branches

Assuming this would be all we want to do on the initial setup branch, we want to merge our branch upwards. What is our destination branch in this case? Since there is no release yet, we are targetting the next release, so the master branch.

Let’s put on our packagist hat for a second. How will we know what went into a release and what didn’t, if we grab all those 3 commits above individually? Fortunately, there’s an easy way of assembling them together as one single entity in the integration branch, known as squashing2; it is an extremely useful method to maintain a clean commit history.

$ git merge --squash AG-0001-initial-setup
$ git commit -v
$ git push origin master

The result can be viewed online, with the mention that I have left the squash message untouched specifically for the reader to get a feel of the defaults.

At this point, let’s remove the feature branch, as we are done with it.

$ git push origin --delete AG-0001-initial-setup

The maintainers of other topic branches are now able (and should) grab all changes in the integration branches early and often, in order to avoid solving complex conflicts later.

Prepare our first release

We have reached an important milestone, our initial setup is in fact valid, so as a team we decide that our work so far should be refered to as “release 0.0.1″.

Check that master is a superset of maint by executing

$ git log master..maint

and validating there are no commits found.

We can now tag the release:

$ git tag -m "initial setup 0.0.1" 0.0.1 master
$ git push --tags

Once the release is done from a coding perspective, we can now hand it over to the packagist. The next step is to tidy up the maintenance branches to reflect the new state of facts.

Since maint reflects the previous release, it would be a good time to spin off a new maint-FORMER-RELEASE to be able to supply quick fixes there. In our case this is not needed, as we don’t have a previous release to refer to.

What is needed, though, is to grab all the new code from master to maint, and we do that by

$ git checkout maint
$ git merge --ff-only master

Pull requests

While we were busy setting the 0.0.1 ground and making it happen, our colleagues were really busy carving out the use cases, and their branch advanced quite nicely. This time, they need their work to be validated by teammates, so they decide to create a pull request to showcase it.

Our example below will use the github UI for the visual part. Prepare the pull request by clicking on the new pull request button.

Prepare to create pull request

Supply a relevant title and description.

Teamwork

When we are happy with the current state, pressing the green Merge pull request button will enable us to bring it to the main branch, in our case master.

github-pull-request-02-description.jpg

A more complex release

For our first release, we did not have something to keep maintaining, so the steps we needed to execute were fewer and simpler. This time it will take a bit more attention from our end.

# always make sure we have the latest and greatest
$ git pull origin master

# check master is superset of maint
$ git log master..maint

# tag and publish
$ git tag -m "use cases described" 0.0.2 master
$ git push --tags

What is different this time? We will need to ensure we can easily fix items in 0.0.1 that get reported to us after we have created 0.0.2. The way to achieve this is to spin off maintenance branch for 0.0.1, and use that for fixes and tags.

$ git branch maint-0.0.1 maint
$ git push origin maint-0.0.1

Now it is safe to update maint to contain the new release.

$ git checkout maint
$ git merge --ff-only master
$ git push origin maint

Conclusion

In the first part of the series, we have started with a working example, then detailed a few rules of the gitworkflows branching strategy, and illustrated them with real commands. Next we shown a few simple and effective rules of working with branches, then prepared a couple of releases and accounted for the specifics of each.

Part two of the series will showcase git flow, another popular branching strategy.


  1. https://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html 
  2. http://www.git-scm.com/docs/git-merge

Create PDF files from Markdown sources in OSX

Create PDF files from Markdown sources in OSX

When Markdown appeared more than 10 years ago, it aimed to make it easier to express ideas in an easy-to-write plain text format. It offers a simple syntax that takes the writer focus away from the formatting, thus giving her time to focus on the actual content.

The market abunds of editors to be used for help with markdown. After a few attempts, I settled to Sublime and its browser preview plugin, which work great for me and have a small memory footprint to accomplish that. To pass the results around to other people, less technical, a markdown file and a bunch of images is not the best approach, so converting it to a more robust format like PDF seems like a much better choice.

Pandoc is the swiss-army knife of converting documents between various formats. While being able to deal with heavy-weight formats like docx and epub, we will need it for the more lightweight markdown. To be able to generate PDF files, we need LaTeX. On OSX, the solution of choice is usually MacTeX.

Setup Pandoc for document conversion

Choose the easy brew way:

$ brew update
$ brew install pandoc

If the above solution is not working, the alternative is to take the cabal route:

$ brew install ghc cabal-install
$ cabal update
$ cabal install pandoc

For those interested, the install page covers each aspect in more depth.

Setup Mactex for PDF generation

$ brew tap phinze/cask
$ brew install brew-cask
$ brew cask install mactex

Generating PDF files

We will use the current article as the example we want to export as PDF. The markdown source is available as a gist.

When trying the output command from the pandoc documentation, we notice there is a problem, as it can’t find pdflatex.

$ pandoc -o out.pdf osx-pdf-from-markdown.markdown
pandoc: pdflatex not found. pdflatex is needed for pdf output.

Let’s check it’s been properly installed and symlink it correctly.

$ ls -lsa /usr/texbin/pdflatex
$ sudo ln -s /usr/texbin/pdflatex /usr/local/bin/

Re-running the output command works correctly and gives us a shiny new PDF file.

$ pandoc -o out.pdf osx-pdf-from-markdown.markdown

Create Beautiful UML Diagrams in Minutes from the JetBrains IDE

A few days ago I needed to assemble together several disparate pieces of information about the current project. Our technology stack is complex, and people have different backgrounds, so I realised that a visual representation in UML would be the best fit.
The current article details how to prepare a working environment using Graphviz and PlantUML in PHPStorm, then goes through the process of creating a simple sequence diagram to use them.

Diagrams: the “why” and the “how”

Created by the Object Management Group, UML is the de-facto standard design language in the software community. If you are not familiar with it, or just need a quick refresher, this article on the developerWorks website is very good.

As I tried a couple of online services, it became increasingly clear that they were not fit for my complex set of interacting components. I then turned to my favorite diagramming, tool Graphviz. It turned out there was no straightforward editor on top of it to do sequence diagrams. Luckily, I pretty quickly found PlantUML, which uses Graphviz for all it diagrams but sequence ones. I was impressed by the amount of integrations it offers so I decided to give it a try, and was amazed with the speed of which I produced the end result.

In the next sections we’ll learn how to get our environment up and running, and then draw a quick example sequence diagram.

Setup

Prerequisite

Installing Graphviz using brew worked perfectly for me.

$ brew install graphviz

If you prefer an alternate method, you can download the package instead.

PlantUML

Internally, our company uses PHPStorm as an IDE for developing PHP code, and IntelliJ idea for the Java bits. I will present details for the PHPStorm users, but the steps should be easy to replicate in other IDEs of the same vendor.

Let’s open the preferences and start looking for new plugins.

01-phpstorm-plugins

We need to search for “PlantUML” and install it.

02-phpstorm-install-plantumlintegration

After restarting the IDE, we notice there are new filetypes available for us to create:

03-phpstorm-newfiletypes

Sequence Diagram example

Let’s create a new UML Sequence diagram, named “demo”. Notice how the .puml extension was automatically added.

04-phpstorm-newumlsequence

The diagram I actually needed to produce is very heavy, and not fit for the purpose of this quick introduction. Then I remembered checking the Clean Coders Yahoo group the other day, and found some Ruby sourcecode they were talking about. I thought it would be a good example to try our new diagram superpowers on, as it’s short.

The first step is to define the participants in our diagram. It’s easier to list them all in the beginning, because this way we can choose the order in which they appear.

05-defineparticipants

We will now add the sequence of events. The PlantUML website has a great page on the various options available, so make sure to check it out.

06-describesequence

The stock look and feel is nice and gets us far. I however felt the need to prettify the end result by introducing some nice formatting options. The manual page for the skinparam command is very helpful.

07-nicelyformatted

Conclusion

After installing Graphviz and PlantUML extension for PHPStorm, we were able to produce a sequence diagram in a few minutes. You can take a look at the final version of the code as we obtained it. The advantage of having these tools available straight from the IDE is that the diagrams can be part of the project code, and be managed together.

HowTo Quickly Erase All Documents from an ElasticSearch Index

Let’s say you are locally developing things using the amazing ElasticSearch technology, and would like to quickly wipe out all documents from a specific index.

Assuming you have ES installed on localhost, and the index name is playground, here’s how you would do it:

curl -XDELETE 'http://localhost:9200/playground/?pretty=true'

And the index is now empty, waiting for test data!

Fix Vagrant problems after Mavericks update

Updated the OSX to 10.9 over the weekend.

While most of the troubles I encountered were caused by PHP 5.3 being completely wiped out and the system getting a stock install of 5.4, there were other minor things which didn’t go quite smoothly.

I use a VirtualBox + Vagrant + puppet combination to work on some side projects, and this was affected in a pretty mysterious way, as can be seen below:

➜  centos64 (master) ✗  vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Importing base box 'theCentos64'...
[default] Matching MAC address for NAT networking...
[default] Setting the name of the VM...
[default] Clearing any previously set forwarded ports...
[default] Creating shared folders metadata...
[default] Clearing any previously set network interfaces...
There was an error while executing `VBoxManage`, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.

Command: ["hostonlyif", "create"]

Stderr: 0%...
Progress state: NS_ERROR_FAILURE
VBoxManage: error: Failed to create the host-only adapter
VBoxManage: error: VBoxNetAdpCtl: Error while adding new interface: failed to open /dev/vboxnetctl: No such file or directory

VBoxManage: error: Details: code NS_ERROR_FAILURE (0x80004005), component HostNetworkInterface, interface IHostNetworkInterface
VBoxManage: error: Context: "int handleCreate(HandlerArg*, int, int*)" at line 68 of file VBoxManageHostonly.cpp

This was not an easy task to fix, as Mavericks is pretty new, and Google doesn’t help very much with finding the solution.

In my case, I discovered that if I restarted VirtualBox things will be working again.

sudo /Library/StartupItems/VirtualBox/VirtualBox restart

So this is not strictly related to Vagrant itself, rather to the VirtualBox provider I was using.

HowTo Easily Upgrade Ruby on Mountain Lion

The default Ruby version coming with Mountain Lion is a bit old
➜  ruby -v
ruby 1.8.7 (2012-02-08 patchlevel 358) [universal-darwin12.0]

If only for staying up-to-date with the latest Ruby version, you will want at least 1.9 on your local machine.

There are multiple ways to achieve this, but I found it easiest to use the Ruby Version Manager. This clever command-line tool gives you the freedom you want, at a minimal cost.

Let’s start by installing it:

➜ curl -L https://get.rvm.io | bash -s stable --ruby

At the time of this writing, the latest Ruby version was 1.9.3, and RVM already installed it on your machine.

All you need to do now is to type
➜ rvm use 1.9.3
➜ ruby -v
ruby 1.9.3p385 (2013-02-06 revision 39114) [x86_64-darwin12.2.1]

In case you will need to return to the default ruby version, this is easily accomplished by
➜ rvm system

The screencast has even more detailed RVM usage, geared towards developers.

Easy Setup of Sencha Command on Your Mac

Prerequisite: If you haven’t done this already, setup Sencha Touch SDK.

Step 1: Download Sencha Cmd from the dedicated page.

Download latest Sencha Cmd from the sencha.com website

 

Step 2: Move the archive to a working folder. I used ~/Documents/Work/learn/sencha.

Step 3: Unpack SenchaCmd-3.0.2.288-osx.app.zip by double-clicking it. You should find the installer in your working directory, like in the picture below.

Step 4: Launch the setup by double-clicking the installer. Proceed to the next step. Accept the license agreement and click Next once more.


Make a note of the installation folder you choose in this step. I used /Users/g/bin. Proceed to the end of the wizard and click Finish.

Step 5: Verify that everything went okay. This is achieved from the command-line, by navigating to the SDK setup folder and launching the sencha command.

Note 1: The Sencha Cmd installer automatically adds its dependencies to the .bashrc settings file. if your favorite shell is not bash, you need to perform an extra-step before the verification works. If you’re a zsh user like me, at the end of your .zshrc file you need to add 2 lines to make this work.


export PATH=/Users/g/bin/Sencha/Cmd/3.0.2.288:$PATH
export SENCHA_CMD_3_0_0="/Users/g/bin/Sencha/Cmd/3.0.2.288"

Don’t forget to reload the settings file:

. ~/.zshrc

Note 2: If you had previous versions of Sencha installed, it’s a good time to cleanup your .bashrc (or .zshrc) file from those occurrences.