Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Commit type before feature is done

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?

like image 941
Alexander Zeitler Avatar asked Apr 16 '20 11:04

Alexander Zeitler


People also ask

What is a feat commit?

feat: a commit of the type feat introduces a new feature to the codebase (this correlates with MINOR in semantic versioning).

What is a conventional commit?

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.

What is commit Linting?

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.


3 Answers

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.

like image 106
customcommander Avatar answered Oct 20 '22 09:10

customcommander


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.

like image 39
matt Avatar answered Oct 20 '22 09:10

matt


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.

like image 40
Acorn Avatar answered Oct 20 '22 09:10

Acorn