Writing commit messages - ULJ-Yale/qunexsdk GitHub Wiki

[TOC]

Overview

Clear commit history and messages are key for enabling efficient code review and clear code history. They provide invaluable information on what and why was done. They record the relevant context "on paper", enable sharing the knowledge with the reviewer and document it for the rest of the team.

To support clear development history, writing commit messages has to be part of the following three rules of managing commits:

  1. Make atomic commits
    Each commit should encapsulate a single related change to the code base. In practice, (i) do not combine multiple unrelated code changes (e.g. a code fix and a new feature) into a single commit, (ii) join multiple code changes that are necessary to implement the same code fix or change in functionality in a single commit (e.g. a change in the function name in function definition, all calls of the function, and related in-line documentation).

  2. Write good commit messages
    The commit message should communicate succintly what and why was done and provide the relevant context. The exact structure and content of the commit messages is described further below.

  3. Revise development history before sharing
    During development process it is often difficult to maintain a development history that would tell a clear "story". E.g. after a commit, a typo is discovered or a method name change is requested. In those cases, to keep up with the first rule, it is advantageous to amend the latest commit or add code changes using git commit --ammend, or to revise the development history using git rebase --interactive to remove, reorder, edit, merge and split commits and generate a clear development progression. Do note that these steps should be done before sharing the code / pushing it to the joint repository.

The structure and content of a commit message

Following the Conventional Commits specification, the commit message should have the following structure:

<type>[(<scope>)]: <description>

[optional body]

[optional footer(s)]

Commit message title

The commit message title is the part of the commit message that is visible in the git log output. It has to clearly describe the changes introduced in the commit. It consists of three parts:

  • type of commit
    The commit type denotes what was the nature of the commit. Use one of the following commit types:

    • feat ... commit adds a new feature
    • fix ... commit provides a bug fix
    • docs ... commit updates the documentation without changing the code
    • style ... commit updates the code formatting without changing the code
    • refactor ... commit refactors production code
    • test ... commit adds test(s) without changing the production code
    • chore ... commit updates versioning, configurations, setup tasks without changing the production code
  • scope of commit
    To provide additional context, the type of commit can be optionally followed by specification of the scope of the commit. scope has to immediately follow type and is provided in the parentheses.

  • description of commit
    The description of the commit is separated from type and optional scope using a colon (:). It has to provide specific, succint information about the content of the commit. It should start with a lowercase, use an imperative tone and end without a period.

When writing commit message title, adhere to the following additional rules:

  • The commit title should not exceed 72 characters in length.
  • In cases when a commit introduces a breaking change, that has to be indicated by an exclamation point (!) immediately before the colon (:).

Note that the commit message title clearly relates to semantic versioning. Specifically:

  • a commit of type fix corresponds to PATCH change in semantic versioning,
  • a commit of type feature corresponds to MINOR change in semantic versioning,
  • a commit that introduces breaking change corresponds to MAJOR change in semantic versioning.

Examples

Commit that introduces a bug fix:

fix: remove race condition in parallel processing of bold images

Commit that introduces a new feature:

feat: add full file checking to validation of processing results

Commit that introduces a breaking change:

refactor!: change study folder structure to support EEG processing

Commit message body

The body of the commit message provides additional context and explanation relevant for the commit. Not all commits are complex enough to warrant additional explanation, so the body is optional, however, strongly encouraged.

The commit body has to be separated from the commit title with an empty line. It is free-form and it may consist of any number of empty line separated paragraphs. Each line of the body should not exceed 72 characters in length.

The message body should provide:

  • context and motivation (why) for the change,
  • a description of what the change does,
  • a discussion of context, impact and alternatives.

The commit body explains what and why was done. It describes the motivation for the change. It provides further detail about what the change accomplishes. It explains how the change fits in the larger context and relates it to previous and/or future changes. It provides information that enables understanding the code at a future date.

When writing the commit message body, follow the following guidelines:

  • use consistent terminology,
  • be as transparent as possible,
  • reread the code and detail what you did,
  • provide as much context as you can,
  • describe tradeofs and choices guiding implementation,
  • use standard markup format (use of markdown is encouraged).

Commit message footer(s)

To provide additional information and references to other sources one or more footers may be provided. The footer(s) have to be separated from the body or title by a blank line. They must consist of a word token that is followed by either :<space> or <space># separator, followed by a string value. With the exception of BREAKING CHANGE, a footer's token must use - in place of whitespace characters. A footer's value may contain spaces and newlines.

If included as a footer, breaking change must consist of uppercase BREAKING CHANGE followed by a colon (:), space and description, e.g., BREAKING CHANGE: sessionsfoldername parameter now has to be provided explicitly when running run_turnkey

The footer(s) can be used to provide information about the issue / bug report ID, the name of the person that reviewed the code, etc.

Note that the information provided in the linked sources (e.g. forum bug report) might not be available at a future date, so do not use footer references as a replacement for detailed commit message body.

Example

Recording issue number of the Discourse forum bug report and reviewer:

Discourse-issue: 69
Reviewed-by: AA

Full commit example

In this example, a code fix was performed in the nitools module. The commit message for the change to nitools was:

fix: Replaced spaces with underscores in g_ExtractGLMVolumes saveoption

When calling commands through connector, spaces within parameter values
are not processed correctly. Also, by convention, individual parameter 
/ option values (i.e. not lists or arbitrary strings) should not have
spaces. For this reason spaces in `by effect`, `by session`, and 
`effect files` options for the saveoption parameter were replaced with 
underscores in documentation. 

In code itself the change was implemented by replacing underscores with
spaces (line 86), so that new parameter values with underscores are 
converted to old expected values and used correctly in the rest of the 
code that remains unchanged. In this way saveoption values can still be
used in without change when printing verbose reports (e.g. lines 179, 
186). Additionally this also provides backward compatibility for any 
code that passes the options with spaces instead of underscores.

Additional issues were identified and fixed in testing:

1/ If effects parameter was specified using an empty string (''), no 
effects were extracted. The code now checks whether the effects 
parameter is an empty string (line 102) so that the empty parameter 
is used correctly when calling img_ExtractGLMEstimates and all effects
are exported.

2/ Code incorrectly checked for `by estimate` saveoption when it should
check for `by effect`, and the appropriate sorting was skipped 
(line 156).

3/ A check for correct saveoption parameter was added. The function now
warns if an invalid option is used and exits (line 87).

trello-card: https://trello.com/c/oEGstAhK

When this commit was integrated into the main QuNex repository, the change was committed without repeating the full body of the commit. Instead the original commit title was used with added scope:

fix(nitools): Replaced spaces with underscores in g_ExtractGLMVolumes saveoption

Resources

Consult the following resources for further information and guidelines:

⚠️ **GitHub.com Fallback** ⚠️