Conventional Commits defines several types for commit messages like feat
, fix
, chore
, ci
etc.
My question is about the workflow if I'm working on a feature whose scope spans several days of work. As a good developer I want to commit early and often but the feature in the sense of Conventional Commits is defined as:
feat
: a commit of the typefeat
introduces a new feature to the codebase (this correlates with MINOR in semantic versioning).
So this type of commit should only be used once (otherwise, a CHANGELOG
generated from these commits would list a lot of features which indeed are only parts of a particular feature).
I'm wondering whats the common workflow to solve commit (and push) early and often using Conventional Commits?
Does everybody squash their commits into a feat: ...
type commit?
Are there other workflows?
Which type of messages are used until the squashing feat
commit?
feat: a commit of the type feat introduces a new feature to the codebase (this correlates with MINOR in semantic versioning).
Conventional Commits is a specification for adding human and machine-readable meaning to commit messages. This is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history, which makes it easier to write automated tools on top of.
Commitlint is a simple tool that lints your commit messages and makes sure they follow a set of rules. It runs as a husky pre-commit hook, that is, it runs before the code is committed and blocks the commit in case it fails the lint checks.
You should only be worried about making atomic commits.
An atomic commit is a set of changes that is releasable on its own. It requires a lot of discipline but the ROI is immense:
git bisect
effectivelyThe Conventional Commits specification doesn't dictate workflow, it's a specification for commit messages that tools can use to automate processes: generating change logs and bumping packages versions for example.
It is also worth noting that squashing unrelated commits completely defeats the point of using the Conventional Commits specification in the first place.
Imagine that you must implement a logout button and by the way all buttons are now a few pixels larger which introduces a breaking change. You actually have two pieces of work:
If you squash these two unrelated changesets into a single commit, you run the risk of releasing a breaking change in a minor release.
What if you didn't need to make these buttons larger in the end? If you didn't squash these two commits, you could simply revert the first commit.
It's not impossible that as you work on a task, you may end up creating a few refactoring commits before fixing a bug or implementing a feature. Perhaps the fix or the feature won't be needed anymore but is that the case for your refactoring commits? These may be valuable changes that you actually needed regardless of the fix or the feature.
There's no good reason for squashing unrelated commits. You may as well keep amending the first and only commit in your codebase yet you wouldn't do that.
Does everybody squash their commits into a feat: ... type commit?
Yes. Well I do. Actually, I work privately on a feature using two branches. One is the feature branch I’ll be pushing for pull review later. The other is a temporary work branch where I save often. Every once in a while I squash merge from the temp onto the end of the feature. So the temp has 30 commits but the feature has 2 or 3. In your case it sounds like you want it to have just one!
Also keep in mind that you can amend, interactively rebase / squash, reset, etc., to rewrite your branch before it is pushed for the first time. So you don't really need two branches; you can use your one branch to save early and often and then completely rewrite your history before pushing.
As a good developer I want to commit early and often
That is "release/publish early and often", not commit. When you commit is not relevant in the standard Git workflow, because commits are local, so they are modifiable before you publish (and you should modify them, see below).
Does everybody squash their commits into a feat: ... type commit? Are there other workflows?
There are many workflows out there and not all are good. For instance, both squashing all commits into one and leaving temporary/"WIP" commits are wrong approaches.
Commits should be independent units of work over time. If your feature can be split into 5 commits that make sense on each own, then you should do that. The point is to make them as easy to understand as possible, as well as revertible as possible.
That is why squashing everything into a single commit makes reviews impossible if the feature is big enough. In a similar fashion, leaving temporary or WIP commits are useless for your log and future research.
I suggest you take a look at how the Git project itself, as well as the Linux kernel (the project it was created for) do it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With