At CharlieHR, we use a rebase and merge strategy to deploy our code. A few months back we started to have problems synchronizing our merges, and ended up using a Slack channel and some simple rules to solve it.
In general, our process looks something like this: an engineer makes a feature branch and does some work. When it’s ready to merge, they:
- Rebase their branch against master and resolve any conflicts.
- Force push the branch to GitHub and wait for the CI build to run. This takes about 10 minutes.
- If CI is green, they use the green github button to either rebase and merge or squash and merge to
master, depending on whether they want to keep the feature branch commit history or not.
- Once the commits are in master, they are automatically deployed to our staging environment and — after some testing — the build is promoted to production on Heroku.
This is all fine and dandy, except for the fact that CI builds take a while. Consider:
- Tim rebases and force pushes his branch. He makes a cup of ☕️ while the build runs.
- Katie does the same a few minutes later.
- Tim’s build is green, so he hits the rebase and merge button, adding his commits to master.
- Katie’s build is also green, except she can’t merge to master because her branch doesn’t contain Tim’s new commits. She’ll have to start the whole process over again 😞.
Although it was sometimes annoying, this wasn’t a massive issue until a few months ago, when people started seeing this way to regularly…
There are probably a couple of reasons it became an problem:
- We have more engineers than we used to, and therefore more merges.
- We’ve started working in cross-functional teams, so we’re less aware of what other engineers are doing.
- We’re working hard to make our pull requests really small so they’re easier to review and debug, so we merge more regularly.
Whatever the reasons, I found myself shouting “I’m rebasing to merge in a minute, has anyone got a final build running?”
Clearly not a sensible solution.
After some discussion on whether we should change our merging strategy, I ended up asking myself: what’s the simplest thing we could do to fix this? It turned out to be a Slack channel called
#dev-merge with these instructions pinned to it…
Some Basic Rules
- Absolutely no posts other than those prescribed below.
- ONLY use threads for conversations that need to happen in here.
- Never leave the team hanging! If you’ve added an “I’m merging” flag, you either need to finish the process or else abandon it (more below).
- Never put a reaction on a post that isn’t yours (unless you merged or deployed for someone else).
- If you see that someone is queued and you’ve just deployed, be nice and send them a DM to let them know the pipeline is free.
Posts in here should take the form:
Rebasing to merge https://github.com/CharlieHR/Charlie/pull/XXX
This is the initial state. A waiting PR is in the queue to get merged. It has no reactions.
This signals that the PR is being rebased, the tests are running or it’s being merged and auto-deployed to staging. It’s represented by a Charlie logo.
This signals that the PR has been merged to master and is deployed to staging. It’s represented by a Green Tick.
This signals that the process has been abandoned, and the post can be ignored. It’s represented by a red cross.
5. Promoted to Production
This signals that the release has been promoted to production. It’s represented by a rocket ship, obviously. This state is less crucial than the others, since it does not block others merging.
The Process to Follow
You should only begin this process when your work has met the Definition of Done.
- Add your post.
- Look at the post directly before yours. If it IS NOT merged (green tick) or abandoned (red cross), then the pipeline is busy. You can make yourself a cup of tea, safe in the knowledge that you’ve signalled your intent to merge. You’re now in the queue.
Once the post before yours has been merged or abandoned, you can get on with your own:
- Add a charlie logo (do this first)
master, checkout your branch and
git rebase master.
- Force push and watch the tests run against your branch. Maybe get some more tea. Your charlie logo is signalling that nobody else should merge while your tests are running.
Once your branch (which now includes all the commits in
master) is green, you should:
- Hit the big green merge button on GitHub. If the commits on your branch are all sensible then you should choose rebase and merge, if you want to squash all of them into one big commit then you should choose squash and merge. If you choose the latter, make sure you edit the commit message so it describes the change. Delete the branch on Github.
- Confirm that your PR deployed to staging without any errors, and any migrations ran ok.
- Add a green tick. Your are now signalling that you have merged to master and are testing on the staging environment. Others can merge if they want to.
- If everything is good on staging, add a rocket ship once you’ve successfully promoted the build to production using the Heroku pipeline.
If you have conflicts, failing tests or you run off to a meeting — or otherwise realise you aren’t ready to merge right now, you must abandon your post by adding a red cross.
Finally, if you have a queued post that you no longer want to merge, you can either abandon it by adding a red cross, or just delete it.
This is what it should look like if you’ve followed the process properly…
The verdict: does it work?
Yep. Well enough for now.
I’m constantly looking for ways to improve our process, so if you have any thoughts on this, drop me a line on twitter.