6

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 type feat 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?

Alexander Zeitler
  • 8,345
  • 7
  • 54
  • 97
  • The question is too broad and opinionated. But I answer the last question. Use [prefix `WIP:`](https://stackoverflow.com/search?q=%5Bgit%5D+wip) which means "work in progress". – phd Apr 16 '20 at 13:00

4 Answers4

3

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:

  • You can release or rollback to any commit
  • You can use git bisect effectively
  • You can target and revert unnecessary changes with more accuracy
  • You can use your Git history effectively to find patterns in your codebase

The 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:

  1. feat: make all buttons larger. BREAKING CHANGE
  2. feat: implement a logout button

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.

customcommander
  • 11,496
  • 3
  • 35
  • 53
  • 1
    I've got a gripe with that `refactor`. Wikipedia, unlike Angular, says that refactoring should *not* change the external behavior. Making all buttons larger is definitely changing the external behavior. – kubanczyk Dec 22 '20 at 10:00
  • @kubanczyk Agreed. This was an oversight from my part but is now fixed. Many thanks. – customcommander Dec 22 '20 at 13:34
2

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.

matt
  • 447,615
  • 74
  • 748
  • 977
  • Thanks for your answer. Do you use conventional commits on the temp branch as well or did you exclude it from the conventions as everything is squashed anyway at some point? If you apply conventional commits here as well, which type do you use then? – Alexander Zeitler Apr 16 '20 at 11:57
  • personally I don't apply any convention because all the commits on the temp branch will be thrown away – matt Apr 16 '20 at 13:06
2

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.

Acorn
  • 22,093
  • 4
  • 30
  • 62
0

We use short lived feature branches. A new version is created when the feature branch is merged back into master. So you could do several feat: commits into your feature branch.

oocx
  • 781
  • 5
  • 7