The backstory
My team and I experienced a bit of drama a few weeks back when a piece of code that was deployed to production caused some unwanted side-effects for our users. The developer that authored that code was on leave and we couldn't contact him easily, so we decided that we should revert that piece of code. Unfortunately, due to the nature of the changes, we needed to revert just a small chunk of that code, and that meant finding the pull request and commits and using that to work out what needed to be reverted.
This was a couple of weeks after the change went live, and our team merges dozens of PRs a day, and pushes hundreds of commits a day - so the changes immediately got swamped in the history (I'm sure you can guess where this is going 🙄).
The problem
We spent over an hour looking for the code that caused the issue, then an additional hour trying to figure out if that was the only change needed to revert, and if that revert could cause more problems that it solved.
This was the offending commit...
The Solution
After we patched the issue we discussed the issue and quickly came to a consensus that we could have fixed the issue faster, had the commit and PR been named correctly.
So we came up with a few guidelines that we would stick to a as team to make sure that all our historical code is findable, understandable and fast to author.
Conventional commits
We follow the Conventional Commits guidelines, this provides a lot of benefits, I will not list them all exhaustively, but here are our favourites:
-
It forces that our commits stay consistent across the team. This ensures every developer knows what to expect when digging through git history.
-
It improves searchability, with conventional commits, you can scope your commits with an "area" that the commit refers to, which can then be searched in git history. e.g.
feat(email): adds method to set from name
. -
They are quick to author. You don't have to write an essay, you just have to state what, and most importantly why.
Why not what
We decided that the why is more important than the what. Take this example; fix: filter null values
. Sure, we know that the code change probably relates to remove null values from some kind of collection. But how much does that actually help us? If you're trying to figure out why a bug has popped up - this won't help you much if you're searching for culprits. fix: filter null recipients in email send
however tells you what area of your logic the change is effecting, and to a large extent -why
. Obviously we do not want to send emails to null@null.null
😁. So for the cost of 3 extra words, you could save yourself an hour of digging too.
Descriptive pull request names
Similarly to good commits, PR names matter when trying to find some historical change or feature that has bubbled up to the surface. They have great scope for showing a history of changes to your repository. At Teemill since implementing these guidelines we use our pull request names to generate a changelog that we curate for our users to inform them of new features and fixes. This forces our team to maintain a high standard of naming PRs well as they'll end up being shown to our users!
An example of a bad PR:
This is non-descriptive and unrelatable, it means little to our users and is too generic to be useful when searching
A better example:
If you read this from the perspective of a user, its now meaningful - you've just sped up their workflow by up to a second. It also increases the searchability of the PR.
No comments yet…