Skip to content

Git Commit Guidelines at Steel Ridge

Contents:

Overview

Origin of this document

The original version of this document was borrowed from the AngularJS team's docs. However, we have since made drastic modifications to this document to suit our practices.

A commit history are an important tool in telling the story of how a code base develops over time. As a result, it's critical these messages are formatted in a standard and consistent manner. Furthermore, many commit messages will be pulled into the product changelog when releasing a new version.

There are some general considerations / rules when writing commit messages:

  • Written in present tense: The top line of the commit message should be readable with the prefix “This commit…” (e.g., “this commit fixes an issue where data was not refreshing”).
  • Reference Jira tickets in the 'refs' section if a commit is relevant (e.g., “refs: PET-162, PET-163”).
  • Reference PR numbers in the 'refs' section for commits related to Pull Request feedback (e.g., “refs: PR #62”).
  • Mention related commit SHAs in the 'refs' section for directly related commits (e.g., “refs: d22821c, 36570b7”).
  • Follow the Commit Message Template
  • Tag the commit with the appropriate tag using the tag specifications below.

Commit Message Template

Each commit message consists of a header, a body and a footer. The header has a special format that includes a type and a subject:

<type>: <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>

The header is mandatory and the scope of the header is optional.

Any line of the commit message should not be longer than 100 characters (although 80 is ideal)! This allows the message to be easier to read on GitHub as well as in various git tools.

Example commit message:

fix (auth): resolve login issue for certain admin users

Resolves an issue where users who didn't have any reports were denied access,
even though they might have admin rights in the system.

refs: RP-1234, RP-4321, PR #745

Commit Types / Prefixes

Commit types (alternatively "Commit Prefixes") help us quickly identify the high-level purpose of a commit when reading the history.

As a general rule, if a commit could be classified as more than one type, it should probably be broken into 2 commits so that both tags are satisfied.

FEAT

  • A new feature or enhancement offering novel value to end-users or administrators.
  • Examples: New screens, screen enhancements, new monitoring functionality, new API routes.
  • Format: “feat: adds new compensation management home screen”.
  • Simple Example: “feat: adds print button to statement page”.
  • Complex Example: Involves multiple stages (e.g., placeholders, API endpoints, services, and final feature addition).

FIX

  • Rectifies bugs or defects in the main/shared code branch.
  • Fixes should not address feature branch defects.
  • Example: “fix: resolves issue where data was not refreshing on xyz screen”.

API

  • Involves creating/modifying API endpoints or updating frontend API modules.
  • Backend Example: “api: adds new API endpoint for fetching all Statement Collections”.
  • Frontend Example: “api: updates frontend API module with latest backend changes”.

DB

  • Changes impacting the database or application-database interactions.
  • Includes structural changes, migrations, SQL scripts, seed data, database contexts.

DOCS

  • Changes to documentation, including markdown docs, inline code documentation, and stored procedure headers.

STYLE

  • Visual alterations that don’t address application issues.
  • Includes CSS/SCSS changes for visual aspects or maintainability.

REFACTOR

  • Code changes that don’t fix bugs or add features but improve software attributes like comprehensibility, complexity, and maintainability.

TEST

  • Involves new tests, fixing or improving existing tests to reflect functionality changes. Covers frontend and backend unit tests.

CHORE

  • General project maintenance changes not affecting functionality.
  • Includes build process configuration, tools/libraries updates, dependency updates, and application tooling updates.

WIP

  • Work-in-progress steps in a larger bug fix, feature, or enhancement effort.
  • Forms part of a broader modification sequence, but does not complete the task in its entirety.

Subject

The subject contains succinct description of the change:

  • use the imperative, present tense: "change" not "changed" nor "changes"
  • don't capitalize first letter
  • no dot (.) at the end

Body

Just as in the subject, use the imperative, present tense: "change" not "changed" nor "changes". The body should include the motivation for the change and contrast this with previous behavior.

The footer should contain any information about Breaking Changes and is also the place to reference the Jira issue(s) that this commit addresses.

Breaking Changes should start with the word BREAKING CHANGE: with a space or two newlines. The rest of the commit message is then used for this.

Revert

If the commit reverts a previous commit, it should begin with revert:, followed by the header of the reverted commit. In the body it should say: This reverts commit <hash>., where the hash is the SHA of the commit being reverted.

Conventional Commits and Configuration

Conventional commits are a specification for adding human and machine-readable meaning to commit messages. This standardization makes it easier to manage and automate changes in your project. To enforce conventional commit messages, you can use a configuration file (e.g. conventional-commits.json) and subsequently set up Git hook scripts.

  1. Create the config File: In your project root, create a file named `conventional-commits.json``.

  2. Define Commit Types: List the types of commits allowed in your project (e.g., feat, fix, etc.). For each type, you can specify a description and whether it's permissible to omit the scope.

  3. Specify Format Rules: Define the format for different parts of the commit message, like type, scope, and subject. Ensure these rules align with your project's requirements and team's preferences.

  4. Add Optional Rules: You can also include rules for body and footer sections of the commit message, specifying line lengths and other formatting preferences.

Here's a basic example of what your conventional-commits.json might look like:

{
  "convention": {
    "commitTypes": [
      "merge",
      "feat",
      "fix",
      "api",
      "db",
      "docs",
      "style",
      "refactor",
      "test",
      "chore",
      "wip"
    ],
    "commitScopes": [],
    "releaseTagGlobPattern": "v[0-9]*.[0-9]*.[0-9]*",
    "issueRegexPattern": "PET-[0-9]+"
  },

  "changelog": {
    "commitTypes": ["feat", "fix", "perf", "merge"],
    "includeInvalidCommits": true,
    "commitIgnoreRegexPattern": "^wip: "
    }
...
}

Using the Configuration

To enforce the rules specified in conventional-commits.json, you need to set up Git hooks. The commit-msg hook is what we use for validating commit messages.

You should follow instructions given by the official Conventional Commit Guidelines and Git Hook Scripts.

After going through their guide, note that the key to enforcing the rules in your current repo is to make the .git-hooks/commit-msg hook executable. You can do this by running the following command in your project root:

chmod +x '.git-hooks/commit-msg'

Then set git hook directory to .githooks

git config core.hooksPath '.git-hooks'

See the Conventional Commit Guidelines and Git Hook Scripts for more details.