Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 142 additions & 33 deletions docs/tutorials/writing_commits.md
Original file line number Diff line number Diff line change
@@ -1,51 +1,160 @@
For this project to work well in your pipeline, a commit convention must be followed.
# Commit Message Best Practices

By default, Commitizen uses the known [conventional commits][conventional_commits], but
you can create your own following the documentation information over at
[customization][customization].
## About

## Conventional commits
For Commitizen to work effectively in your development pipeline, commits must follow a consistent convention. By default, Commitizen uses the [Conventional Commits][conventional_commits] specification, which provides a standardized format for commit messages that enables automatic versioning and changelog generation.

If you are using [conventional commits][conventional_commits], the most important
thing to know is that you must begin your commits with at least one of these tags:
`fix`, `feat`. And if you introduce a breaking change, then you must
add to your commit body the following `BREAKING CHANGE`.
Using these three keywords will allow the proper identification of the semantic version.
Of course, there are other keywords, but I'll leave it to the reader to explore them.
You can also create your own custom commit convention by following the [customization documentation][customization].

Note: You can also indicate breaking changes by adding an exclamation mark in the commit title
(e.g., `feat!: breaking change`) by setting the `breaking_change_exclamation_in_title`
configuration option to `true`. [Read more][breaking-change-config]
## Conventional Commits Format

## Writing commits
The Conventional Commits specification follows this structure:

Now to the important part: when writing commits, it's important to think about:
```
<type>[optional scope]: <description>

- Your future self
- Your colleagues
[optional body]

You may think this is trivial, but it's not. It's important for the reader to
understand what happened.
[optional footer]
```

Emojis may be added as well (e.g., see [cz-emoji][cz_emoji]), which requires the `utf-8`, or equivalent, character encoding to support unicode characters. By default, `commitizen` uses the `utf-8` character encoding, but a different encoding may be set through the `encoding` [configuration option][configuration].
### Commit Types

### Recommendations
Commit types categorize the nature of your changes. The most important types for semantic versioning are:

- **Keep the message short**: Makes the list of commits more readable (~50 chars).
- **Talk imperative**: Follow this rule: `If applied, this commit will <commit message>`
- **Think about the CHANGELOG**: Your commits will probably end up in the changelog,
so try writing for it, but also keep in mind that you can skip sending commits to the
CHANGELOG by using different keywords (like `build`).
- **Use a commit per new feature**: If you introduce multiple things related to the same
commit, squash them. This is useful for auto-generating CHANGELOG.
- **`feat`**: Introduces a new feature (correlates with **MINOR** version increment)
- **`fix`**: Patches a bug (correlates with **PATCH** version increment)

| Do's | Don'ts |
| ---- | ------ |
Other commonly used types include:

- **`docs`**: Documentation only changes
- **`style`**: Code style changes (formatting, missing semicolons, etc.)
- **`refactor`**: Code refactoring without changing functionality
- **`perf`**: Performance improvements
- **`test`**: Adding or updating tests
- **`build`**: Changes to build system or dependencies
- **`ci`**: Changes to CI configuration files
- **`chore`**: Other changes that don't modify source or test files

!!! note
While `feat` and `fix` directly affect semantic versioning, other types (like `build`, `chore`, `docs`) typically don't trigger version bumps unless they include a `BREAKING CHANGE`.

### Breaking Changes

Breaking changes trigger a **MAJOR** version increment. You can indicate breaking changes in two ways:

1. **In the commit body or footer**:
```
feat(api): change authentication method

BREAKING CHANGE: The authentication API now requires OAuth2 instead of API keys.
```

2. **In the commit title** (when enabled):
```
feat!: change authentication method
```

To enable this syntax, set `breaking_change_exclamation_in_title = true` in your configuration. [Read more][breaking-change-config]

### Scope

An optional scope can be added to provide additional context about the area of the codebase affected:

```
feat(parser): add support for JSON arrays
fix(api): handle null response gracefully
```

## Writing Effective Commit Messages

Well-written commit messages are crucial for maintaining a clear project history. When writing commits, consider:

- **Your future self**: You'll need to understand these changes months later
- **Your team**: Clear messages help colleagues understand the codebase evolution
- **Automated tools**: Good messages enable better changelog generation and versioning

### Best Practices

#### 1. Keep the Subject Line Concise

The subject line should be clear and concise (aim for ~50 characters). It should summarize what the commit does in one line.

**Good:**
```
fix(commands): handle missing user input gracefully
feat(api): add pagination support
```

**Avoid:**
```
fix: stuff
feat: commit command introduced
```

#### 2. Use Imperative Mood

Write commit messages in the imperative mood, as if completing the sentence: "If applied, this commit will..."

**Good:**
```
feat: add user authentication
fix: resolve memory leak in parser
```

**Avoid:**
```
feat: added user authentication
fix: resolved memory leak in parser
```

#### 3. Think About the Changelog

Your commits will likely appear in the automatically generated changelog. Write messages that make sense in that context. If you want to exclude a commit from the changelog, use types like `build`, `chore`, or `ci`.

#### 4. One Feature Per Commit

Keep commits focused on a single change. If you introduce multiple related changes, consider squashing them into a single commit. This makes the history cleaner and improves changelog generation.

#### 5. Use the Body for Context

For complex changes, use the commit body to explain:

- **Why** the change was made
- **What** was changed (if not obvious from the subject)
- **How** it differs from previous behavior

```
feat(api): add rate limiting

Implement rate limiting to prevent API abuse. The system now
enforces a maximum of 100 requests per minute per IP address.
Exceeding this limit returns a 429 status code.
```

### Examples

| ✅ Good Examples | ❌ Poor Examples |
| ---------------- | ---------------- |
| `fix(commands): bump error when no user provided` | `fix: stuff` |
| `feat: add new commit command` | `feat: commit command introduced` |
| `feat(api): add pagination to user list endpoint` | `feat: commit command introduced` |
| `docs: update installation instructions` | `docs: changes` |
| `refactor(parser): simplify token extraction logic` | `refactor: code cleanup` |

## Character Encoding

Commitizen supports Unicode characters (including emojis) in commit messages. This is useful if you're using commit message formats that include emojis, such as [cz-emoji][cz_emoji].

By default, Commitizen uses `utf-8` encoding. You can configure a different encoding through the `encoding` [configuration option][configuration].

## Related Documentation

- [Conventional Commits Specification][conventional_commits]
- [Custom Commit Conventions][customization]
- [Commit Configuration Options](../config/commit.md)

[customization]: ../customization/config_file.md
[conventional_commits]: https://www.conventionalcommits.org
[cz_emoji]: https://commitizen-tools.github.io/commitizen/third-party-commitizen/#cz-emoji
[cz_emoji]: ../third-party-plugins/cz-emoji.md
[configuration]: ../config/commit.md#encoding
[breaking-change-config]: ../config/commit.md#breaking_change_exclamation_in_title
2 changes: 1 addition & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ nav:
- Customized Python Class: "customization/python_class.md"
- Changelog Template: "customization/changelog_template.md"
- Tutorials:
- Writing commits: "tutorials/writing_commits.md"
- Commit Message Best Practices: "tutorials/writing_commits.md"
- Managing tags formats: "tutorials/tag_format.md"
- Auto check commits: "tutorials/auto_check.md"
- Auto prepare commit message: "tutorials/auto_prepare_commit_message.md"
Expand Down