Commits, Pull Requests and the two-sided coin of contributing
Although it was a bit late for my career, in the few last years I’ve been working closely with the entire Git architecture and how online services like GitHub, BitBucket etc. operate and grow, offering more and more interesting features to their users.
My engagement with git and source control in general includes building my own projects (both open and closed source), watching other open source projects with their guidelines and developing for my company. In numbers, this means that I was interacting with a decent amount of commits and pull requests per week. Recently I started taking the responsibility as release manager and this is the time when it really hit me.
Contribution is not about open source projects, is about delivering code in the best possible way to your colleagues.
It doesn’t matter if the code you are writing targets an open source project or your company’s internal project and service. It is your contribution to the project codebase and you have to be proud of it every single day.
When your team lead is trying to set the guidelines for a good structure regarding commits and pull requests, the goal is to facilitate both developers that write code and developers that review code and release features. This means that some guidelines might seem to you as redundant and a waste of time like “Do I really need to write all this description here?” or “Let’s just write ‘fix bug’ and it will be fine, I remember what this is all about”. Well, guess again, you won’t remember.
Before going any further describing a good structure of commits and pull requests, we have to analyse the different environments that a company might have in order to release a PRPI (Potentially Releasable Product Increment).
You might be familiar of the concept of Continuous Delivery. It’s a very popular workflow that allows teams to deliver code faster. This might be different among various teams, but in general it means that every push to a branch is immediately available to your stakeholders.
We can all agree that it’s a bit risky to deliver continuously to production as it increases the risk of breaking things. So, almost every company has a qa/staging environment where they test internally all the features before they hit production at the end of the sprint/circle. In our case, we also have another environment which is called ‘dev’ and is used for contracts, meaning that when the frontend has to be synced with the backend (in this case we have separate repositories for frontend and backend), we deploy to dev for the sync and then send to qa. Having a good structure and being able to define these contracts in advance, the dev environment shouldn’t exist. In a nutshell, these are the most common environments:
- QA / Staging
- Dev (optional)
So, the goal of this article is to be able to identity at any given moment which features are resolved and are ready for testing, which features on your qa/staging environment and which features are going to be released to production in the next deployment.
Reading Chris Beams’ blog How to Write a Git Commit Message, paved the way of building a good culture within my team and my company in general. It is a good guideline to have an organized commit history. If the commit is related to a specific task id, you can formulate a good summary like this:
[task-id]: short descriptive task title
I would like to avoid diving into much detail about branching, but the generic idea is to have one branch for each environment. Right now the workflow is linear and it goes like this:
- Master ← QA ← Dev ← Feature-branch
- Master ← Master-hotfix
- QA ← QA-hotfix
And if you follow a good release cycle, you can create a new major release branch on every release. I’m a big fan of Vincent Driessen’s post, A successful Git branching model. And the deployment to different environments follows a specific model:
- Dev: deploy on every push
- QA: deploy daily and on hotfixes
- Master/Production: Manually when the PRPI is ready
In the above case we make a Pull request from right to left and we back-merge (no pull request here) from left to right to bring hotfixes to the feature branches. Having said that, Pull requests are the most important part of the project that tell us which feature is at which branch simply by looking at the Pull request merge history.
Since GitHub and BitBucket don’t show in detail which branches are being merged, we usually follow a simple format:
- Normal PRs ( → dev): Normal PR summary
- Feature PRs ( → dev): [feature-id]: Feature summary
- Repository Issue PRs ( → dev): [repo-issue-id]: Issue title
- Merge branch (not a feature): [parent-branch-name] ← [child-branch-name]
The above format allows me to easily see which feature is ready for qa and which hotfixes have been deployed. Unfortunately GitHub doesn’t have a feature to sort PRs by merge date but there are workarounds (if you happen to work at GitHub, maybe you can take a look, thanks).
One last thing about Pull requests is the size. I believe this applies to both open and closed source projects. I’ve reviewed PRs with 100 lines diff and PRs with up to 8000 lines diff (ok, there was some auto-generated code as well in there). The first ones are a lot faster and to the point whilst the big ones were very hard to review. In general, big PRs need much more time for review, although authors might expect for some reason that the review time will be the same.
There is no optimal size for Pull requests. I would highly suggest to break PRs to make it easy for the reviewer. Personally, small reviews will be finished in an acceptable amount of time in between the rest of my tasks, but for big reviews I have to spend much more time, time taken from other tasks and even break it in more than one day.
I can only mention here that there are very good templates out there that can really help you create a very good Pull request description and provide all the needed information that a reviewer might need. Usually this description should be a summary of the finished work (ex. features), test coverage and other useful comments.
It is essential to build a good culture within your (development) team and you can understand the level of contribution (and the code quality) by the amount of trace-ability in your project.
The very first value of the Agile Manifesto is:
Individuals and Interactions over Processes and Tools
Take some time to communicate what and why, as this could be a framework, brainstorm to make this even better and more suitable to your company’s needs and you can easily see that the processes can help you move faster.
If you believe this is a good way to contribute and trace your features and your work, hit the recommendation button and spread the word! Please feel free to comment and discuss :-)