0%

Git Conventions For Naming Branches And Commit Messages

How to name branches and write commit messages when using git? A thorough summary of all usual conventions is given below.

Branch Naming Convention

Git branches can generally be separated into two categories:

Code Flow Branches

These branches which we expect to be permanently available on the repository follow the flow of code changes starting from development until the production.

  • Development
    All new features and bug fixes should be brought to the development branch. Resolving developer codes conflicts should be done as early as here.

  • Master
    The production branch, if the repository is published, this is the default branch being presented.

Temporary Branches

Category

A temporary git branch should start with a category. Pick one of these: feature, bugfix, hotfix, or test.

  • feature
    Any code changes for a new module or use case should be done on a feature branch. This branch is created based on the current development branch. When all changes are Done, a Pull Request/Merge Request is needed to put all of these to the development branch.

  • bugfix
    If the code changes made from the feature branch were rejected after a release, sprint or demo, any necessary fixes after that should be done on the bugfix branch.

  • hotfix
    If there is a need to fix a blocker, do a temporary patch, apply a critical framework or configuration change that should be handled immediately, it should be created as a Hotfix. It does not follow the scheduled integration of code and could be merged directly to the production branch, then on the development branch later.

  • test
    is for experimenting outside of an issue/ticket

Reference

After the category, there should be a “/“ followed by the reference of the issue/ticket you are working on. If there’s no reference, just add no-ref.

Description

After the reference, there should be another “/“ followed by a description which sums up the purpose of this specific branch. This description should be short and “kebab-cased”.

By default, you can use the title of the issue/ticket you are working on. Just replace any special character by “-“.

To sum up, follow this pattern when branching:

1
git branch <category/reference/description-in-kebab-case>

Examples

You need to add, refactor or remove a feature:

1
feature/issue-42/create-new-button-component

You need to fix a bug:

1
bugfix/issue-342/button-overlap-form-on-mobile

You need to fix a bug really fast (possibly with a temporary solution):

1
hotfix/no-ref/registration-form-not-working

You need to experiment outside of an issue/ticket:

1
test/no-ref/refactor-components-with-atomic-design

Commit Naming Convention

Commit Message Format

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

1
2
3
4
5
<type>[optional scope]: <subject>

[optional body]

[optional footer(s)]

Type

Must be one of the following:

  • feat for a new feature for the user, not a new feature for build script. Such commit will trigger a release bumping a MINOR version.
  • fix for a bug fix for the user, not a fix to a build script. Such commit will trigger a release bumping a PATCH version.
  • perf for performance improvements. Such commit will trigger a release bumping a PATCH version.
  • docs for changes to the documentation.
  • style for formatting changes, missing semicolons, etc.
  • refactor for refactoring production code, e.g. renaming a variable.
  • test for adding missing tests, refactoring tests; no production code change.
  • build for updating build configuration, development tools or other changes irrelevant to the user.
  • ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
  • revert: reverts a previous commit. Begins with revert: , followed by the header of the reverted commit. In the body it should say: This reverts commit ., where the hash is the SHA of the commit being reverted.
  • chore: Update something without impacting the user (updating grunt tasks bump a dependency in package.json. no production code change).

Scope(optional)

Scope can be anything specifying place of the commit change.

  • init
  • runner
  • watcher
  • config
  • web-server
  • proxy
  • etc.

Subject

The subject contains a succinct description of the change:

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

Body(optional)

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 GitHub issues that this commit Closes.

Breaking changes

Breaking Changes should start with the word BREAKING CHANGE: with a space or two newlines. The rest of the commit message is then the description of the change, justification and migration notes.

BREAKING CHANGE example with two newlines

1
2
3
4
5
6
7
BREAKING CHANGE:

`port-runner` command line option has changed to `runner-port`, so that it is
consistent with the configuration file syntax.

To migrate your project, change all the commands, where you use `--port-runner`
to `--runner-port`.

BREAKING CHANGE example with a space

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
BREAKING CHANGE: isolate scope bindings definition has changed and
the inject option for the directive controller injection was removed.

To migrate the code follow the example below:

Before:

scope: {
myAttr: 'attribute',
myBind: 'bind',
myExpression: 'expression',
myEval: 'evaluate',
myAccessor: 'accessor'
}

After:

scope: {
myAttr: '@',
myBind: '@',
myExpression: '&',
// myEval - usually not useful, but in cases where the expression is assignable, you can use '='
myAccessor: '=' // in directive's template change myAccessor() to myAccessor
}

The removed `inject` wasn't generaly useful for directives so there should be no code using it.

Any commit with the breaking change section will trigger a MAJOR release and appear on the changelog independently of the commit type.

Referencing issues

Closed bugs should be listed on a separate line in the footer prefixed with “Closes” keyword like this:

1
Closes #234

or in case of multiple issues:

1
Closes #123, #245, #992

Commit Message Examples

Standard commit message

1
2
3
4
5
6
fix(middleware): ensure Range headers adhere more closely to RFC 2616

Add one new dependency, use `range-parser` (Express dependency) to compute
range. It is more well-tested in the wild.

Closes #2310

Commit message with no body

1
docs: correct spelling of CHANGELOG

Commit message with scope

1
feat(lang): add Polish language

Commit message with body and footer

1
2
3
4
5
6
7
8
feat($browser): onUrlChange event (popstate/hashchange/polling)

Added new event to $browser:
- forward popstate event if available
- forward hashchange event if popstate not available
- do polling when neither popstate nor hashchange available

Breaks $browser.onHashChange, which was removed (use onUrlChange instead)

Commit message with multi-paragraph body and multiple footers

1
2
3
4
5
6
7
8
9
10
fix: prevent racing of requests

Introduce a request id and a reference to latest request. Dismiss
incoming responses other than from latest request.

Remove timeouts which were used to mitigate the racing issue but are
obsolete now.

Reviewed-by: Z
Refs: #123

Commit message with body and footer of referencing issue

1
2
3
4
5
6
7
8
fix($compile): couple of unit tests for IE9

Older IEs serialize html uppercased, but IE9 does not...
Would be better to expect case insensitive, unfortunately jasmine does
not allow to user regexps for throw expectations.

Closes #392
Breaks foo.bar api, foo.baz should be used instead

Commit message with multi-paragraph body and footer of BREAKING CHANGE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
feat($compile): simplify isolate scope bindings

Changed the isolate scope binding options to:
- @attr - attribute binding (including interpolation)
- =model - by-directional model binding
- &expr - expression execution binding

This change simplifies the terminology as well as
number of choices available to the developer. It
also supports local name aliasing from the parent.

BREAKING CHANGE: isolate scope bindings definition has changed and
the inject option for the directive controller injection was removed.

To migrate the code follow the example below:

Before:

scope: {
myAttr: 'attribute',
myBind: 'bind',
myExpression: 'expression',
myEval: 'evaluate',
myAccessor: 'accessor'
}

After:

scope: {
myAttr: '@',
myBind: '@',
myExpression: '&',
// myEval - usually not useful, but in cases where the expression is assignable, you can use '='
myAccessor: '=' // in directive's template change myAccessor() to myAccessor
}

The removed `inject` wasn't generaly useful for directives so there should be no code using it.

References