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

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.

Gemfile Conflicts with XCode

Having a problem with gemfile conflicts – different gems needing different versions and clashing. Cocoapods was the main problem, with a native iOS app we were trying to run in XCode having an old version of cocoapods and not updating, causing problems running the app in the simulator. Note: We are using version 5.1.1 of XCode (XCode 6 caused so many problems with our project so we don’t use it for now) and GitHub to store our repository.

1. rm Gemfile lock

This will delete your Gemfile, located in the root of your project, where the workspace should be, for example, if you are running an iOS app.

2. bundle install

Make sure that your project is not open while running this command, otherwise it may not work properly. This will show you what your conflictions are, if you have any, otherwise it will simply build. The problem we had was:

problem

So we have a conflict with versions for the netrc gem. cocoapods need version 0.7.8, rest-client needs 0.8.0.

3. Open your Gemfile and look at the gems:

source 'https://rubygems.org'

gem "nokogiri", "1.6.1"
gem "cocoapods", "~> 0.35.0"
gem "rspec"
gem "rest-client"
gem "anticipate"
gem "rake"
gem "xcodebuild-rb"
gem "cucumber"
gem "calabash-cucumber"
gem "shenzhen"
gem "CFPropertyList", "~> 2.2.1"
gem "mail"
gem "mimic"
gem "pry"

We updated our cocoapods to include the latest version and above (~> means including and above) and we needed to add a new gem:

gem "netrc", "~> 0.7.8"

This then stopped the conflict, as dependency issues are now solved.

To see what rubies there are, use:

rvm list

To see the gem sets that are installed, use:

rvm gemset list

To see the current gemset:

rvm gemset name
4. bundle install

To install your dependencies, once your Gemfile has been updated and saved.

5. pod install

Update cocoapods. Make sure that your project is closed before running this as it can sometimes cause problems.

6. pod --version

To double check your version of cocoapods.

7. git status

To see the changes that may need to be committed.

Useful links for gemsets:

http://rvm.io/gemsets/basics

http://rvm.io/gemsets/listing