Github Branch Strategy and Solving Merge Conflicts

Branching

I haven’t written much about tech in a while. As I am still in the process of transitioning from a software engineer to a UX person, I thought it would be good to share a bit about how we use Github to work as a team.

I personally feel that designers that work closely with engineers in a team is a great thing. Designers should learn the basics of how to add assets to projects and how to upload files into Github for collaboration, as well as some basic coding. However, this isn’t always the case, but that is a discussion for another post. I really enjoy having a  mix of both jobs, not only as it’s fun and very rewarding being able to focus on design and still code as well, but it’s also a massive benefit to the team and saves developers time on menial tasks, overall resulting in a better product.

Anyway, I digress.

Our strategy (I’m not sure whether it has a name) helps us as a team collaborate with each other, stakeholders and our users. Our main branches are develop, staging and production. All of these branches have fully functional production code with test coverage and CI. We all get a new build release when any code is pushed to any of these branches.

Develop – Developer code. Developers use this as our base branch – this is where we will branch off from when beginning a new feature. Developers only get notified when code is pushed into this branch. Develop is then pushed into staging.

Staging – Stakeholder’s view this branch. When our feature(s) are in develop and ready, they are pushed into staging and a new build is released for stakeholders to view, where they can check everything is as it should be. Staging data is used. Once approval has been gained, staging can be merged into production.

Production – Our master branch. Full production code, released to users and uses live data. Devices with an existing version of the application will be prompted to update (if native), else changes will be seen on web-apps instantly. Developers, stakeholders and users all get build notifications from production.

When all of this has been setup for a project and we get new features in to produce, we begin by branching off of develop. We name our branches according to whether our tasks are features, chores or bugs. Multiple tasks can be worked on at once across the team, but regular pulls from develop are needed to minimise build conflicts. Rarely, if multiple devs want to work on the same feature, a feature branch will be created and this can be branched off (see diagram). This can be useful if someone is halfway through a feature branch and something else is needed from another team member to complete the feature. Of course, multiple developers can always work off the same feature branch, but I prefer to branch off to minimise problems.

Before any branch is put into develop, a pull request is submitted and (a) member(s) of the team will review and then push to develop. Sometimes there can be merge conflicts, but these can easily be solved using git mergetool.

Rarely, we will have a problem with merging staging into production (native Android has been giving us this problem mainly due to conflicts in the manifest file with version numbers). It can seem daunting when having merge conflicts going into production/master, so here are the steps we use to solve this:

  • Make sure staging and production are FULLY up to date with their remote branches (git pull origin).
  • Pull production INTO staging.
  • Open up git mergetool when prompted and fix the merge conflict in the editor part of the program (if version number, when in doubt use a higher number).
  • Commit changes to staging.
  • Pull request from staging into production: all should be able to merge automatically.

I am aware that many dev teams use different strategies in git but this is the one that works best for us. I recently worked in a team that used git flow and found it not to be as effective, but each to their own. Also, always remember to use git prune 🙂 too many branches gets confusing!

Advertisements

GenyMotion Quick Fix

I have been setting up Geny Motion today to run with Android Studio, and was having difficulty setting up. Followed the instructions and installed Virtual Box v5.0, yet was still getting the error “Unable to load VirtualBox engine’.

For once Stack Overflow wasn’t very useful (omg), so got this fix off a colleague (http://www.codingtofu.com/) so thought it would be good to share further. And yes, you do have to sudo. Quick and simple:

sudo cp /usr/local/bin/VBoxManage /usr/bin/VBoxManage

Handy Color Code for Custom Values in Swift

So that RGB values can be entered in XCode in Swift (for example changing the background colour of a table view), place this UIColorExtensions file in your code:

import Foundation
import UIKit
func UIColorFromRGB(rgbValue: UInt) -> UIColor {
    return UIColor(
        red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
        green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
        blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
        alpha: CGFloat(1.0)
    )
}

Then call it in your viewDidLoad() or wherever you want using:

        view.backgroundColor = UIColorFromRGB(0x209624)

Very useful for custom colors in Swift.

Setting up Homebrew, Node, Bower, Grunt & more

We use a variety of Homebrew, Node, NPM, Bower, Grunt and Compass in the majority of our web-apps to aid us with managing our packages and dependencies. From having messed this process up on my machine numerous times now, I am going to document this process so that it may help others in the future, as the Internet was not the most useful of places when I was trying to sort this out by myself. Luckily a colleague has saved the day for me numerous times, so to avoid annoying him further, here is our process 🙂

Note: This process is just to set up a clean install on our machines – I will explain further in another post how to get all of this working within a specific project.

Grunt

Step 1 – Install Homebrew

$ ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)”

Homebrew installs packages and then links their files for you. It is very important that you do this step before anything else so that you can then install packages through Brew, to save having symlink problems later on due to duplicate versions being installed. Install Brew wherever you like.

Step 2 – Install node

$ brew install node

Node.js is a platform built on Javascript’s runtime, great for building real-time applications. When you install node, it comes with npm, its package manager. Npm is great – through this we can install bower, grunt as well as many others that may be needed for future applications.

$ node -v

$ npm -v

Run these commands just to check that your current versions are up to date.

Step 3 – Install Bower

$ npm install -g bower

Bower is another package manager that manages your libraries, frameworks etc. This command will install Bower into your node_modules. Use  a bower.json file to list your packages and the versions that you want – Bower will take care of the rest.

Step 4 – Install Grunt

$ npm install -g grunt-cli

Grunt is a js task runner. Configure a gruntfile.js to automate your tasks using the many plugins available. This makes unit testing, real-time changes and minification so much easier. This task also installs the grunt command line interface.

Step 5 – Install rvm

RVM manages your rubies and shows which ruby your current shell points to. This step may vary for different people. You may need to install gpg (this verifies signatures and publishers) as Mac OSX doesn’t do this for you. If this is the case install it through brew:

$ brew install gnupg gnupg2

Once you have this verification step set up, you need to install this public key necessary for rvm:

$ gpg –keyserver hkp://keys.gnupg.net –recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3

Then you can run the command for installing rvm. If the above steps are already configures, you can skip straight to this:

$ \curl -sSL https://get.rvm.io | bash

To start using rvm, when the last command has finished running, you should see something like “* To start using RVM you need to run `source /Users/UserName/.rvm/scripts/rvm` in all your open shell windows, in rare cases you need to reopen all shell windows.” so run:

$ source /Users/UserName/.rvm/scripts/rvm

Now we need to install some rubies, as we currently will only have the OSX ruby, which requires sudo (NEVER do a sudo – if you need to sudo, something is wrong with your setup). To see available rubies:

$ rvm list

And no rubies should be installed yet.

$ rvm install ruby

To install your rubies.

$ which ruby

Shows your installed rubies – should show rubies in your user path. Now that there is an rvm ruby installed, you own it and can ‘gem-‘ install things without needing to sudo. If these steps hadn’t been done, you would have got an error saying you didn’t have access when trying to gem- install things.

Step 6 – Install compass

$ gem install compass

Installs a gem for compass.

$ npm install compass

Installs compass using npm into your node_modules.

Step 7 – Install selenium

$ brew install selenium-server-standalone

Selenium is needed for automating your web browsers for when you run your tests. If you don’t have tests or think you don’t need this, then wrong – write some tests for your code!

Step 8 – Install chromedriver

$ npm install chromedriver

A wrapper for selenium – also needed for running your tests.

Step 9 – Install Protractor

$ npm install -g protractor

We use Angular, so this is needed for running our end to end tests in the browser. If you don’t user Angular, you won’t need this. Highly recommend using Angular though – it’s awesome. This will install cl protractor and webdriver-manager.

$ webdriver-manager update

Download the binaries to get selenium running.

$ webdriver-manager start

Start up a selenium web server. You may get a pop-up requesting that you download a Java JDK to use the cli. Do this if you haven’t already done so.

Will update some more later to show how to link all this up to your projects to get them running, if you can’t figure it out yourselves 🙂

Merge Conflicts From Branch To Branch On Github

Occasionally, there will be a time when you are merging one branch into another on Github (in our case, develop into staging, as our branch hierarchy goes newBranch(es) -> develop -> staging -> master *) and although it may seem scary when that grey box appears, it isn’t difficult to fix. In the example below, we are pushing to develop from staging:

git checkout develop
git pull origin develop
git checkout staging
git status (all should be up to date).
git merge develop
git mergetool (then press 'enter', fix the conflict using the mergetool, save and close, then type 'y' when prompted).
git status (should show you the changed file ready for committing. There may be a '.orig' file duplicated of the file with the conflict - this can be deleted).
git commit -m "Fixed merge conflicts"
git push origin head

This should solve any problems, unless you’ve got a complicated merge on your hands.

* our branch structure is this way not only to avoid merge conflicts and issues, but to fit in with stakeholders’ features. Each branch has to be merged into develop then deleted. Each contributor will be pulling from develop just in case there are any changes. After develop is ready to be shown to stakeholders and test users, with stakeholder warning and approval, develop is pushed into staging. Only after the stakeholder has approved of the changes in staging can staging go into production (master). The main thing we have to be careful of with this is possible problems when the stakeholder doesn’t like a feature in staging, when someone has already pushed another new feature into develop. To avoid this, all contributors have their own branches to work on, and only push to develop when a staging feature has been approved and is being pushed to develop. All the while that they are working on their features, they are pulling from develop to stay up to date.

Excluding Events During Development and Testing in Google Analytics

A very helpful post here: http://tjvantoll.com/2012/08/28/google-analytics-excluding-visits-in-development-and-production/ After googling for an answer, finally found this. Excellent and much easier approach to not logging your own visits in Google Analytics. Our analytics are extremely inaccurate due to our developers testing our sites during development, staging and production. Rather than having to change the UA ID every single time we want to test, then having to change it back again for production, we can add the code shown in the blog to block local host from logging. I appreciate that, at first, we have to test without blocking ourselves just to check that GA itself is logging our pageviews and events (unless we are very confident), but after that we can have more valid results. Unless we carry on making another project with GA and then copy the code, it’s never going to be 100% accurate, but this method will be pretty close. Even works for the production site too: the js will just help us visit an alternate URL which will have the analytics off. We have had to do some slight changes to the code for us as follows:

if (window.location.host != 'localhost:9000') {
 ga('create', 'UA-xxxxxxxx-xx', 'auto'); //insert your tracking ID here
 ga('send', 'pageview');
 var _gaq = _gaq || [];
 _gaq.push(['_setAccount', 'UA-12345678-1']);
 _gaq.push(['_trackPageview']);
(function() {
 var ga = document.createElement('script');
 ga.type = 'text/javascript';
 ga.async = true;
 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
 var s = document.getElementsByTagName('script')[0];
 s.parentNode.insertBefore(ga, s);
 })();
 }

We have had to adjust the original GA code slightly so that it will not log for localhost, but still log for other addresses such as 0.0.0.0. We will investigate further for blocking this and covering all ports in case they get changed. Currently, it only covers localhost:9000 to not track data.

NOTE: This method ONLY excludes events – pageviews are still tracked. The best way to track pageviews accurately is to set up an event and then only use the data from the event for your statistics.

Unfortunately our data is already flawed due to the testing If anyone has found any other solutions that are easier or more accurate then please share!