As a developer, we spend everyday in a plethora of development activities. While the processes (agile, scrum etc.) ensure all of them add business value, I think only a few enrich the product meaningfully. Imagine if we could measure our activities; understand the activities that help with engineering and those that add direct value (bug fix or a feature). Knowing the gaps can make us efficient.
In this post, we will discuss semantic commits as a way to measure our activities.
Let’s start with a few examples of semantic commits and derive a definition.
Semantic commits - definition
The karma test runner defines commit messages in the following
schema. type
is project independent attribute, whereas scope
is dependent on
the project and it’s constituent components. This schema helps in generating
a readable (noise-free) summary of interesting changes, and with release notes
or changelogs.
<type>(<scope>): message
<body>
<footer>
---
type: feat, fix, docs, style, refactor, test, chore
scope: init, runner, watcher etc.
Such annotations can help derive a sense of effort from git logs. For example,
given below is a year worth of git commits in karma
(master branch).
> cd /tmp/karma
> git log --pretty=oneline --no-merges --since 2017/01/01 --until 2017/12/31 | cut -d " " -f 2 |\
cut -d "(" -f 1 | cut -d ":" -f 1 | sort -r | uniq -c | sort -nr -k1
39 chore
28 fix
23 feat
15 docs
6 test
2 Try
1 refactor
Using the scope annotation we could further slice and dice this data into questions like which component has most number of bug fixes?.
A slight variation of this approach is recommended by angularjs
developers. It doesn’t provide a chore
annotation, instead it suggests
build
and ci
. There’s a perf
annotation as well.
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
---
type: feat, fix, docs, style, refactor, test, perf, build, ci
scope: animations, common, compiler etc.
Conventional commits takes meaning to next level drawing a relationship with semver. The format is minimal with several optional annotations.
<type>[optional scope]: <description>
[optional body]
[optional footer]
---
type: `fix` corresponds to `PATCH` of semver
type: `feat` corresponds to `MINOR` of semver
body or footer with `BREAKING CHANGE` corresponds to `MAJOR` of semver
Let’s quickly recap the essence of semantic commits.
Why semantic commits?
Semantic commits add meaning to each commit message through annotations. They are primarily used for:
- Keeping a changelog of all commits. More at keep a changelog.
- Human readable project history
- Ease of release and auditing ([semantic] commits -> [semantic] version)
- Measuring and classification of effort
These guidelines enable consumers make literate decisions about using a
particular app or library. We started this discussion with (4)
as the primary
motivation and saw an example from karma
repository. If we could account for
fixes versus chores, and features versus tests; could it help infer a
thing or two about productivity as a developer?
May be. I’ve just recently started following this religiously. We will come back to review the question in a few weeks time.
Coming back, how do we enable semantic commits in a developer workflow?
Enabling semantic commits
There are two simple ways to achieve this. Please choose the one that suits you. And do let me know if there’s another better way!
1. Using git commands
Install a few git commands for the specific commit types. Use them with git like
git chore "add build scripts for travis.
.
Follow the instructions at https://github.com/fteem/git-semantic-commits.
2. Using git aliases
Use git aliases feature to provide alias
for semantic commits. Add the
following to ~/.gitconfig
:
# Contents of ~/.gitconfig
# A complete example is at https://github.com/codito/configs/blob/master/.gitconfig
[alias]
cdo = "!f() { git commit -m \"docs: $1\"; }; f"
cfe = "!f() { git commit -m \"feat: $1\"; }; f"
cfi = "!f() { git commit -m \"fix: $1\"; }; f"
cho = "!f() { git commit -m \"chore: $1\"; }; f"
clo = "!f() { git commit -m \"localize: $1\"; }; f"
cre = "!f() { git commit -m \"refactor: $1\"; }; f"
cst = "!f() { git commit -m \"style: $1\"; }; f"
cte = "!f() { git commit -m \"test: $1\"; }; f"
Use it like git cho "add build scripts for travis."
.
Read more about awesomeness of aliases at git wiki. Have patience
and read through the Collection of git aliases
section. That’s going to
enlighten you if this is your first encounter with aliases ;)
There’s a slightly different approach to alias-based-semantic-commits at http://adrianwong.fun/semantic-commit-messages/.
Bonus
If emojis are your thing, delight yourself with a few of these.
And while we’re talking about git, commits and functionality; be sure to checkout the git extras. We’ll probably do a summary walkthru of extras here in future.
That’s 851 words for today. Namaste and wish you fantastic 2018!