Red Green Repeat Adventures of a Spec Driven Junkie

How I migrated the team to SkullCandy git Workflow

In my last post : talked why and what results we achieved

This post: talk HOW we migrated, sharing areas I messed up in the migration and eventual success.

I walk through steps I took in changing team from gitflow to SkullCandy git workflow, the problems I encountered and solutions applied.

If you’re changing your team’s git workflow, you’ll definitely learn from our lessons! (or maybe see why you don’t want to change?)

This article will take you about six minutes to read.

Bartolomé Estéban Murillo - Female Saint Holding Skull source and more information

Introduction

I changed the team’s code workflow from gitflow to skullcandy git workflow. There are reasons and I discuss them in the previous article.

Looking back, I stand behind the reasons and found better results with SkullCandy git workflow than expected.

At the same time, there were bumps along the way in getting to everyone working with SkullCandy git workflow smoothly.

While writing this article, I know I failed in executing change management. If you’re reading this, you will learn from my mistakes!

Original Plan

After researching and deciding that Skullcandy was the workflow the team would adopt, I had a plan to introduce the change.

The way the change would happen is at the next staff meeting:

  1. Describe problem
  2. Present solution
  3. Go through mechanics
  4. Next problem!

Simple enough, right?

How Change Actually Happened

I did steps one, two, and three from above, the problem was there were numerous steps from three to four that I did not anticipate with the team.

Looking back at the staff meeting discussions, there were about six months of steps between steps three and four.

These are the highlights from the six months.

The First “remaster”

After the staff meeting, I deleted the current develop branch and made a new version based on the master branch, just as planned.

One thing I didn’t anticipate: teammates still had work in progress that was not in the master branch and still on the develop branch.

This effectively caused their work to disappear.

If you ever got stressed out about screwing up work on your own git repository, imagine when you delete a team’s work.

That was not a fun two days where team members had to recover/redo work. (Good thing their repositories were forks, right?!)

We’re off to a great start, aren’t we? 😅

(I call making a new develop branch from master branch a “remaster”.)

Next Meeting

Let’s just say the next staff meeting was: painful!

Why can’t we just go back to the old way?!

Now the objections are appearing!

I wanted more than one data point to reverse course and also only if that data point was insurmountable.

The Next Remaster

From the first remaster experience, I learned to do two things before remastering:

  1. I announce that I would remaster the develop branch
  2. Make a “backup” of the develop branch

This gave a warning to team members about keeping an eye on their work and also a backup develop branch just in case. Losing work is no fun, redoing work because of the workflow is even less.

Everyone prepared for this change and had their work in order before the remaster. After creating the new develop branch, it was business as usual.

The Next, Next Remaster

Since the last remaster went well, we just kept working for the next sprints.

Then I realized we did not remaster the develop branch for a long time. Remastering develop did not happen for at least two sprints.

We need to remaster.

Since there were numerous commits to develop and master, there was conflicts getting work from the develop branch onto the master branch.

Work wasn’t lost, the problem was that the branches diverged and any work based on the develop branch would not apply cleanly to the master branch.

It was painful for team members that worked on long lived branches based on the develop branch.

At least there was no yelling at the next staff meeting. That’s a good sign, right?? 😄

Remastering Regularly

From the last experience, even though we were not following SkullCandy git workflow exactly, regular remastering is essential. This is where I made the rule to remaster the develop branch regularly, with the start of the sprint, regardless of state.

This encourages finishing work before the end of the sprint so work one can cleanly apply their changes to master.

If one had to carry over work to the next branch, the change to master would be small.

This also keeps the develop branch in sync with the master branch.

With this change, the team was in sync and I felt benefits of the SkullCandy git workflow over gitflow.

Our Implementation of SkullCandy git Workflow

This is a step by step guide on how we implement the SkullCandy git workflow in our process.

Start (or End) of sprint

  • backup existing develop branch
  • “remaster” develop: make new develop branch from master
  • rebase any existing work against new develop

At the start of the sprint, this is important as it keeps work fresh against proper branch (ultimately, master).

During sprint

  • merge new work into develop branch for testing
  • merge work for deployment into master

To apply work on develop branch and to easily apply changes to the master branch, the team has been using git cherry-pick.

Squash Commits

To make everyone’s life easier using the SkullCandy git workflow, squash commits down. git cherry-pick is a great tool, it also gets really gnarly to move multiple commits over time. git commit --amend --no-edit is your friend.

If in git-hole

git reflog is your friend. Even if you lost the commits in git, they are still there and you can dig your way out. My article:

How-to Dig Out of git reset “git hole”

Special Note: Database Schema Files

Take extra caution for any files that store the database schema. Ruby on Rails has a strict ordering on its database files (schema.rb / structure.sql).

When making changes against such a file, ensure the database schema is the version from the master branch before applying changes.

Deployments

  • deploys to non-production environments are automatic from develop or master branch
  • deploys to production environments are manual from master branch

note: if a production revert is necessary - there are two ways:

  1. Make a revert commit to master branch OR
  2. Deploy with different SHA/tag from the deployment system

In over two years of using SkullCandy git workflow, I only had to revert production twice. The team tested their code in develop branch then applied to master branch. Everything in master branch is clean.

Feedback from Team

After two years of using SkullCandy git workflow with the team, the team is confident and this comments (totally unbiased! 😊)

Relaxing - I don’t have to worry about reverting work in progress from ‘release branch’.

Everyone is confident master has items for production deploy.

It took some getting used to and it’s fine now.

Whew - I did not feel I would get to comments like this the first months of the changing over to SkullCandy git workflow.

If Doing Again?

Whew - the change, while seemingly simple, still took at least six months to fully integrate and be confident in using.

Change Management

If I had to do this all over again, I would definitely do research into change management. A complete oversight until I started writing this article.

Let Team Solve Problem

One thing I wish I did to get better buy in from the team was to let the team solve the original problem (increase deployment frequency) to see what solution they arrive at.

If they come to a different solution, they will be running with it. If it’s the same, they would be on board with the changes.

More tactical changes I would do to improve the change:

Remaster Sooner & Frequently

At the time, the team had gitflow down pat. The first remasters were painful because we kept old habit of having the develop branch as long-lived, similar in gitflow. Remastering the develop branch sooner and more frequently would help in getting out of that mindset.

Change Branch Names

When migrating from gitflow to SkullCandy git workflow, we used the same branch names, develop & master. This was nice that there was not much to change, in reality, there were bigger changes underneath.

Changing branch names would have been a strong signal of changes underneath and everyone would know things are different, and we are not just working with gitflow.

Insights

Casual thoughts I developed from using gitflow and SkullCandy git workflow.

Inheritance vs. Composition

In gitflow, the master branch inherits code from the working branch, develop. This includes any partial commits, reverts, etc.

While in SkullCandy git workflow, code composes the master branch of final changes (based on the develop branch, based on the master branch). The code is the final draft of that work and the best version. No partial commits or reverts.

Code & Data Flow

With SkullCandy git workflow, code flows from the master branch to develop branch.

In gitflow, code flows from develop branch into master branch.

Usually, master branch is the version deployed on production and develop branch is the version deployed on non-production systems.

SkullCandy git workflow’s code parallels the data flow: non-production system will accept production data, while the converse will always be false!

This is one aspect I appreciate about SkullCandy git workflow, it mirrors the data, production first.

Conclusion

Originally solving a deployment frequency problem turned into a six month change management with a little work lost, increased skills managing code in git, and an improved confidence in deploying code.

After using SkullCandy git workflow, I see the differences compared to gitflow and enjoy the benefits of SkullCandy over gitflow.

If you are changing the team’s git workflow and would like advice, feel free to contact me and I can answer questions I didn’t cover in this article.