|
1 | | -For this project to work well in your pipeline, a commit convention must be followed. |
| 1 | +# Commit Message Best Practices |
2 | 2 |
|
3 | | -By default, Commitizen uses the known [conventional commits][conventional_commits], but |
4 | | -you can create your own following the documentation information over at |
5 | | -[customization][customization]. |
| 3 | +## About |
6 | 4 |
|
7 | | -## Conventional commits |
| 5 | +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. |
8 | 6 |
|
9 | | -If you are using [conventional commits][conventional_commits], the most important |
10 | | -thing to know is that you must begin your commits with at least one of these tags: |
11 | | -`fix`, `feat`. And if you introduce a breaking change, then you must |
12 | | -add to your commit body the following `BREAKING CHANGE`. |
13 | | -Using these three keywords will allow the proper identification of the semantic version. |
14 | | -Of course, there are other keywords, but I'll leave it to the reader to explore them. |
| 7 | +You can also create your own custom commit convention by following the [customization documentation][customization]. |
15 | 8 |
|
16 | | -Note: You can also indicate breaking changes by adding an exclamation mark in the commit title |
17 | | -(e.g., `feat!: breaking change`) by setting the `breaking_change_exclamation_in_title` |
18 | | -configuration option to `true`. [Read more][breaking-change-config] |
| 9 | +## Conventional Commits Format |
19 | 10 |
|
20 | | -## Writing commits |
| 11 | +The Conventional Commits specification follows this structure: |
21 | 12 |
|
22 | | -Now to the important part: when writing commits, it's important to think about: |
| 13 | +``` |
| 14 | +<type>[optional scope]: <description> |
23 | 15 |
|
24 | | -- Your future self |
25 | | -- Your colleagues |
| 16 | +[optional body] |
26 | 17 |
|
27 | | -You may think this is trivial, but it's not. It's important for the reader to |
28 | | -understand what happened. |
| 18 | +[optional footer] |
| 19 | +``` |
29 | 20 |
|
30 | | -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]. |
| 21 | +### Commit Types |
31 | 22 |
|
32 | | -### Recommendations |
| 23 | +Commit types categorize the nature of your changes. The most important types for semantic versioning are: |
33 | 24 |
|
34 | | -- **Keep the message short**: Makes the list of commits more readable (~50 chars). |
35 | | -- **Talk imperative**: Follow this rule: `If applied, this commit will <commit message>` |
36 | | -- **Think about the CHANGELOG**: Your commits will probably end up in the changelog, |
37 | | - so try writing for it, but also keep in mind that you can skip sending commits to the |
38 | | - CHANGELOG by using different keywords (like `build`). |
39 | | -- **Use a commit per new feature**: If you introduce multiple things related to the same |
40 | | - commit, squash them. This is useful for auto-generating CHANGELOG. |
| 25 | +- **`feat`**: Introduces a new feature (correlates with **MINOR** version increment) |
| 26 | +- **`fix`**: Patches a bug (correlates with **PATCH** version increment) |
41 | 27 |
|
42 | | -| Do's | Don'ts | |
43 | | -| ---- | ------ | |
| 28 | +Other commonly used types include: |
| 29 | + |
| 30 | +- **`docs`**: Documentation only changes |
| 31 | +- **`style`**: Code style changes (formatting, missing semicolons, etc.) |
| 32 | +- **`refactor`**: Code refactoring without changing functionality |
| 33 | +- **`perf`**: Performance improvements |
| 34 | +- **`test`**: Adding or updating tests |
| 35 | +- **`build`**: Changes to build system or dependencies |
| 36 | +- **`ci`**: Changes to CI configuration files |
| 37 | +- **`chore`**: Other changes that don't modify source or test files |
| 38 | + |
| 39 | +!!! note |
| 40 | + 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`. |
| 41 | + |
| 42 | +### Breaking Changes |
| 43 | + |
| 44 | +Breaking changes trigger a **MAJOR** version increment. You can indicate breaking changes in two ways: |
| 45 | + |
| 46 | +1. **In the commit body or footer**: |
| 47 | + ``` |
| 48 | + feat(api): change authentication method |
| 49 | +
|
| 50 | + BREAKING CHANGE: The authentication API now requires OAuth2 instead of API keys. |
| 51 | + ``` |
| 52 | +
|
| 53 | +2. **In the commit title** (when enabled): |
| 54 | + ``` |
| 55 | + feat!: change authentication method |
| 56 | + ``` |
| 57 | +
|
| 58 | + To enable this syntax, set `breaking_change_exclamation_in_title = true` in your configuration. [Read more][breaking-change-config] |
| 59 | +
|
| 60 | +### Scope |
| 61 | +
|
| 62 | +An optional scope can be added to provide additional context about the area of the codebase affected: |
| 63 | +
|
| 64 | +``` |
| 65 | +feat(parser): add support for JSON arrays |
| 66 | +fix(api): handle null response gracefully |
| 67 | +``` |
| 68 | +
|
| 69 | +## Writing Effective Commit Messages |
| 70 | +
|
| 71 | +Well-written commit messages are crucial for maintaining a clear project history. When writing commits, consider: |
| 72 | +
|
| 73 | +- **Your future self**: You'll need to understand these changes months later |
| 74 | +- **Your team**: Clear messages help colleagues understand the codebase evolution |
| 75 | +- **Automated tools**: Good messages enable better changelog generation and versioning |
| 76 | +
|
| 77 | +### Best Practices |
| 78 | +
|
| 79 | +#### 1. Keep the Subject Line Concise |
| 80 | +
|
| 81 | +The subject line should be clear and concise (aim for ~50 characters). It should summarize what the commit does in one line. |
| 82 | +
|
| 83 | +**Good:** |
| 84 | +``` |
| 85 | +fix(commands): handle missing user input gracefully |
| 86 | +feat(api): add pagination support |
| 87 | +``` |
| 88 | +
|
| 89 | +**Avoid:** |
| 90 | +``` |
| 91 | +fix: stuff |
| 92 | +feat: commit command introduced |
| 93 | +``` |
| 94 | +
|
| 95 | +#### 2. Use Imperative Mood |
| 96 | +
|
| 97 | +Write commit messages in the imperative mood, as if completing the sentence: "If applied, this commit will..." |
| 98 | +
|
| 99 | +**Good:** |
| 100 | +``` |
| 101 | +feat: add user authentication |
| 102 | +fix: resolve memory leak in parser |
| 103 | +``` |
| 104 | +
|
| 105 | +**Avoid:** |
| 106 | +``` |
| 107 | +feat: added user authentication |
| 108 | +fix: resolved memory leak in parser |
| 109 | +``` |
| 110 | +
|
| 111 | +#### 3. Think About the Changelog |
| 112 | +
|
| 113 | +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`. |
| 114 | +
|
| 115 | +#### 4. One Feature Per Commit |
| 116 | +
|
| 117 | +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. |
| 118 | +
|
| 119 | +#### 5. Use the Body for Context |
| 120 | +
|
| 121 | +For complex changes, use the commit body to explain: |
| 122 | +- **Why** the change was made |
| 123 | +- **What** was changed (if not obvious from the subject) |
| 124 | +- **How** it differs from previous behavior |
| 125 | +
|
| 126 | +``` |
| 127 | +feat(api): add rate limiting |
| 128 | + |
| 129 | +Implement rate limiting to prevent API abuse. The system now |
| 130 | +enforces a maximum of 100 requests per minute per IP address. |
| 131 | +Exceeding this limit returns a 429 status code. |
| 132 | +``` |
| 133 | +
|
| 134 | +### Examples |
| 135 | +
|
| 136 | +| ✅ Good Examples | ❌ Poor Examples | |
| 137 | +| ---------------- | ---------------- | |
44 | 138 | | `fix(commands): bump error when no user provided` | `fix: stuff` | |
45 | | -| `feat: add new commit command` | `feat: commit command introduced` | |
| 139 | +| `feat(api): add pagination to user list endpoint` | `feat: commit command introduced` | |
| 140 | +| `docs: update installation instructions` | `docs: changes` | |
| 141 | +| `refactor(parser): simplify token extraction logic` | `refactor: code cleanup` | |
| 142 | +
|
| 143 | +## Character Encoding |
| 144 | +
|
| 145 | +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]. |
| 146 | +
|
| 147 | +By default, Commitizen uses `utf-8` encoding. You can configure a different encoding through the `encoding` [configuration option][configuration]. |
| 148 | +
|
| 149 | +## Related Documentation |
| 150 | +
|
| 151 | +- [Conventional Commits Specification][conventional_commits] |
| 152 | +- [Custom Commit Conventions][customization] |
| 153 | +- [Commit Configuration Options](../config/commit.md) |
46 | 154 |
|
47 | 155 | [customization]: ../customization/config_file.md |
48 | 156 | [conventional_commits]: https://www.conventionalcommits.org |
49 | | -[cz_emoji]: https://commitizen-tools.github.io/commitizen/third-party-commitizen/#cz-emoji |
| 157 | +[cz_emoji]: ../third-party-plugins/cz-emoji.md |
50 | 158 | [configuration]: ../config/commit.md#encoding |
51 | 159 | [breaking-change-config]: ../config/commit.md#breaking_change_exclamation_in_title |
0 commit comments