commitfmt-windows-x64 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -56
- package/commitfmt.exe +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,22 +19,39 @@
|
|
|
19
19
|
</a>
|
|
20
20
|
</p>
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
commitfmt is an opinionated formatter and configurable linter for Git commit messages. Designed primarily for use in a Git `prepare-commit-msg` hook, it helps keep commit history clean and readable.
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
## Quick start
|
|
25
|
+
|
|
26
|
+
The example below installs commitfmt as a local npm development dependency. See [Installation](#installation) for standalone and Python alternatives.
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install --save-dev commitfmt
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Try the default formatting mode:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
printf '%s\n' "feat ( parser ) : add new option." | npm exec -- commitfmt
|
|
36
|
+
# feat(parser): add new option
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then add `npm exec -- commitfmt` to a Git `prepare-commit-msg` hook using one of the [hook examples](#hook). No configuration is required for formatting. To enforce project-specific rules, add a [configuration file](#configuration) to the repository root.
|
|
40
|
+
|
|
41
|
+
See [Modes](#modes) for the difference between formatting a message, linting a message, and checking commit history.
|
|
25
42
|
|
|
26
43
|
## Features
|
|
27
44
|
|
|
28
45
|
### Formatting
|
|
29
46
|
|
|
30
|
-
|
|
47
|
+
By default, commitfmt transforms a message like this:
|
|
31
48
|
|
|
32
49
|
```
|
|
33
50
|
feat ( scope , scope ) : add new feature.
|
|
34
51
|
body description
|
|
35
52
|
```
|
|
36
53
|
|
|
37
|
-
into well-formatted message:
|
|
54
|
+
into a well-formatted message:
|
|
38
55
|
|
|
39
56
|
```
|
|
40
57
|
feat(scope, scope): add new feature
|
|
@@ -44,9 +61,9 @@ body description
|
|
|
44
61
|
|
|
45
62
|
### Linting
|
|
46
63
|
|
|
47
|
-
commitfmt can
|
|
64
|
+
commitfmt can enforce project-specific commit rules.
|
|
48
65
|
|
|
49
|
-
For example,
|
|
66
|
+
For example, to restrict commit types and scopes, add the following to the [configuration file](#configuration):
|
|
50
67
|
|
|
51
68
|
```toml
|
|
52
69
|
[lint.header]
|
|
@@ -62,22 +79,24 @@ exists = ["Issue-ID", "Authored-By"]
|
|
|
62
79
|
|
|
63
80
|
### Performance
|
|
64
81
|
|
|
65
|
-
commitfmt is
|
|
82
|
+
commitfmt is designed for low-overhead local hooks. The [comparison benchmark](docs/benchmark.md) records mean latency and throughput for commitfmt and commitlint when checking the current commit and a 10-commit history range.
|
|
66
83
|
|
|
67
|
-
|
|
84
|
+
## Installation
|
|
68
85
|
|
|
69
|
-
|
|
70
|
-
| --- | --- |
|
|
71
|
-
| macOS | x86_64, arm64 |
|
|
72
|
-
| Windows | x86_64, i686 |
|
|
73
|
-
| Linux | x86_64, i686, arm64 |
|
|
86
|
+
Prebuilt binaries are available for the following platforms and installation methods:
|
|
74
87
|
|
|
75
|
-
|
|
88
|
+
| OS | Installation script | npm or pip |
|
|
89
|
+
| --- | --- | --- |
|
|
90
|
+
| macOS | x64, arm64 | x64, arm64 |
|
|
91
|
+
| Windows | x64, x86, arm64 | x64, arm64 |
|
|
92
|
+
| Linux | x64, x86, arm64 | x64, arm64 |
|
|
76
93
|
|
|
77
94
|
### Script
|
|
78
95
|
|
|
79
96
|
You can use a simple [script](https://github.com/mishamyrt/commitfmt/blob/refs/heads/main/scripts/install.sh) to install commitfmt.
|
|
80
|
-
It
|
|
97
|
+
It downloads and installs the latest prebuilt binary.
|
|
98
|
+
|
|
99
|
+
The installer requires Bash, `curl` or `wget`, and the appropriate archive tools: `tar` on macOS and Linux, with `xz` or `unxz` as a fallback, or `unzip` on Windows. On Windows, run it from Git Bash, MSYS2, or Cygwin. The binary is installed in `/usr/local/bin` when that directory is writable; otherwise, it is installed in `~/.local/bin`.
|
|
81
100
|
|
|
82
101
|
```bash
|
|
83
102
|
# Install latest version
|
|
@@ -110,9 +129,9 @@ pip install commitfmt
|
|
|
110
129
|
|
|
111
130
|
## Hook
|
|
112
131
|
|
|
113
|
-
After installing
|
|
132
|
+
After installing commitfmt, add a Git `prepare-commit-msg` hook. You can configure it manually or use any hook manager.
|
|
114
133
|
|
|
115
|
-
> **
|
|
134
|
+
> **Command used in hooks:** the examples below assume an installation made with the script or pip and use the direct `commitfmt` command. For a local Node.js development dependency, replace it with `pnpm exec commitfmt`, `npm exec -- commitfmt`, or `yarn exec commitfmt`.
|
|
116
135
|
|
|
117
136
|
### Script
|
|
118
137
|
|
|
@@ -130,13 +149,17 @@ Add to your `lefthook.yml` file:
|
|
|
130
149
|
|
|
131
150
|
```yaml
|
|
132
151
|
prepare-commit-msg:
|
|
133
|
-
|
|
134
|
-
|
|
152
|
+
jobs:
|
|
153
|
+
- name: format commit message
|
|
154
|
+
run: commitfmt
|
|
155
|
+
args: ""
|
|
135
156
|
```
|
|
136
157
|
|
|
158
|
+
`args` is intentionally empty: Lefthook otherwise forwards Git hook arguments, while commitfmt locates Git's `COMMIT_EDITMSG` itself.
|
|
159
|
+
|
|
137
160
|
### [Husky](https://github.com/typicode/husky)
|
|
138
161
|
|
|
139
|
-
|
|
162
|
+
Create `.husky/prepare-commit-msg` with the following content:
|
|
140
163
|
|
|
141
164
|
```bash
|
|
142
165
|
#!/bin/sh
|
|
@@ -145,29 +168,29 @@ commitfmt
|
|
|
145
168
|
|
|
146
169
|
## Configuration
|
|
147
170
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
It is an opinionated formatter and the author has established best practices that should not harm anyone.
|
|
171
|
+
Core formatting behavior, such as removing extra whitespace, is intentionally not configurable. This keeps formatted commit messages consistent and predictable across a project. Project-specific constraints can be configured using the lint rules below.
|
|
151
172
|
|
|
152
173
|
### Linting
|
|
153
174
|
|
|
154
|
-
Most
|
|
175
|
+
Most linting rules are disabled by default. Two rules are enabled because the formatter can fix them safely:
|
|
155
176
|
|
|
156
177
|
```toml
|
|
157
178
|
[lint.header]
|
|
158
|
-
description-full-stop = true
|
|
179
|
+
description-full-stop = true # Remove trailing periods from header descriptions
|
|
159
180
|
|
|
160
181
|
[lint.footer]
|
|
161
|
-
breaking-exclamation = true
|
|
182
|
+
breaking-exclamation = true # Add ! for BREAKING CHANGE or BREAKING-CHANGE
|
|
162
183
|
```
|
|
163
184
|
|
|
164
|
-
|
|
185
|
+
Breaking-change footer keys are case-sensitive. commitfmt recognizes `BREAKING CHANGE` and `BREAKING-CHANGE`; `BREAKING CHANGES` is not supported.
|
|
165
186
|
|
|
166
|
-
|
|
187
|
+
To enable more rules, create a `.commitfmt.toml` or `commitfmt.toml` file in the root of your Git repository. commitfmt loads the configuration from the repository root even when it is run from a subdirectory. If both files exist, `.commitfmt.toml` takes precedence. Available lint rules can be found in the [rules.md](https://github.com/mishamyrt/commitfmt/blob/main/crates/commitfmt-linter/docs/rules.md) file.
|
|
188
|
+
|
|
189
|
+
In the default formatting mode, safe fixes are applied automatically. The command fails on violations that cannot be fixed; when used as a hook, this aborts the commit. In `--lint` mode, the message is never modified and any violation causes a non-zero exit code.
|
|
167
190
|
|
|
168
191
|
#### Unsafe fixes
|
|
169
192
|
|
|
170
|
-
Some rules may be
|
|
193
|
+
Some rules have fixes that may be undesirable in certain contexts. For example, adding a period to the end of a body may distort an embedded log. Rules with unsafe fixes are marked in the same `rules.md` file.
|
|
171
194
|
|
|
172
195
|
To enable unsafe fixes, add the following to your config file:
|
|
173
196
|
|
|
@@ -178,13 +201,20 @@ unsafe-fixes = true
|
|
|
178
201
|
|
|
179
202
|
### Extending
|
|
180
203
|
|
|
181
|
-
|
|
204
|
+
To reuse another configuration, add `extends` with a path relative to the current configuration file:
|
|
182
205
|
|
|
183
206
|
```toml
|
|
184
207
|
extends = "node_modules/commitfmt-config-standard/commitfmt.toml"
|
|
185
208
|
```
|
|
186
209
|
|
|
187
|
-
|
|
210
|
+
Only one inheritance level is supported. If the referenced configuration also contains `extends`, commitfmt returns an error.
|
|
211
|
+
|
|
212
|
+
Configuration inheritance uses a shallow merge:
|
|
213
|
+
|
|
214
|
+
- top-level parser options from the current file override inherited values
|
|
215
|
+
- redefining `[lint.header]`, `[lint.body]`, or `[lint.footer]` replaces the entire inherited group; groups omitted from the current file remain inherited
|
|
216
|
+
- `[lint]` options from the current file replace inherited `[lint]` options, so repeat `unsafe-fixes = true` when the current file defines lint settings and still needs unsafe fixes
|
|
217
|
+
- additional footers from the current file are appended after inherited footers
|
|
188
218
|
|
|
189
219
|
### Parser Configuration
|
|
190
220
|
|
|
@@ -208,7 +238,7 @@ By default, commitfmt uses git's `core.commentChar` or `core.commentString` conf
|
|
|
208
238
|
comment-symbol = "//"
|
|
209
239
|
```
|
|
210
240
|
|
|
211
|
-
|
|
241
|
+
Comment lines immediately after the header and at the end of the commit message are ignored during parsing. Comment lines elsewhere are preserved as message content, and the header is always parsed as content.
|
|
212
242
|
|
|
213
243
|
### Additional footers
|
|
214
244
|
|
|
@@ -231,10 +261,12 @@ You can use shell commands to dynamically generate footer values:
|
|
|
231
261
|
```toml
|
|
232
262
|
[[additional-footers]]
|
|
233
263
|
key = "Authored-By"
|
|
234
|
-
value = "{{
|
|
264
|
+
value = "{{ printf %s \"$USER\" }}"
|
|
235
265
|
```
|
|
236
266
|
|
|
237
|
-
|
|
267
|
+
Commands are executed with `sh -c`. The `sh` executable and any external commands must be available through `PATH`; shell built-ins such as `printf` require no separate executable. A non-zero exit code aborts formatting, and trailing line endings are removed from standard output before it is used as the footer value.
|
|
268
|
+
|
|
269
|
+
> **Security:** shell templates execute arbitrary commands. Use configuration files only from trusted sources.
|
|
238
270
|
|
|
239
271
|
#### Branch value pattern
|
|
240
272
|
|
|
@@ -243,13 +275,13 @@ You can also add the ticket number from the task tracker to the footer if it is
|
|
|
243
275
|
```toml
|
|
244
276
|
[[additional-footers]]
|
|
245
277
|
key = "Ticket-ID"
|
|
246
|
-
branch-pattern = "(
|
|
278
|
+
branch-pattern = "^(?:[^/]+/)*(?<TICKET_ID>[A-Z][A-Z0-9]*-[0-9]+)(?:/.*)?$"
|
|
247
279
|
value = "${{ TICKET_ID }}"
|
|
248
280
|
```
|
|
249
281
|
|
|
250
282
|
For example, if your branch name is `feature/CC-123/add-new-feature` or `feature/CC-123`, the `Ticket-ID` footer will be added to the commit message with the value `CC-123`.
|
|
251
283
|
|
|
252
|
-
If the
|
|
284
|
+
The named capture is available to the value template as `TICKET_ID`. If the current branch is unavailable or does not match the pattern, the footer is skipped.
|
|
253
285
|
|
|
254
286
|
Branch patterns use the [regex-lite syntax](https://docs.rs/regex-lite/latest/regex_lite/#syntax).
|
|
255
287
|
Unicode character classes and Unicode-aware case folding are not supported.
|
|
@@ -258,34 +290,34 @@ Unicode character classes and Unicode-aware case folding are not supported.
|
|
|
258
290
|
|
|
259
291
|
Examples of patterns for branch names in git flow format:
|
|
260
292
|
|
|
261
|
-
- Jira/YouTrack:
|
|
293
|
+
- Jira/YouTrack: `^(?:[^/]+/)*(?<TICKET_ID>[A-Z][A-Z0-9]*-[0-9]+)(?:/.*)?$`
|
|
262
294
|
- `feature/CFMT-123`
|
|
263
295
|
- `feature/CFMT-123/add-new-feature`
|
|
264
|
-
- GitHub:
|
|
296
|
+
- GitHub: `^(?:[^/]+/)*(?<ISSUE_ID>[0-9]+)(?:/.*)?$`
|
|
265
297
|
- `feature/123`
|
|
266
298
|
- `feature/123/add-new-feature`
|
|
267
299
|
|
|
268
300
|
#### On conflict
|
|
269
301
|
|
|
270
|
-
If the
|
|
302
|
+
If the message already contains a footer with the same key, `on-conflict` determines whether commitfmt adds the configured footer. The existing footer is never removed.
|
|
271
303
|
|
|
272
304
|
```toml
|
|
273
305
|
[[additional-footers]]
|
|
274
306
|
key = "Ticket-ID"
|
|
275
|
-
branch-pattern = "(
|
|
307
|
+
branch-pattern = "^(?:[^/]+/)*(?<TICKET_ID>[A-Z][A-Z0-9]*-[0-9]+)(?:/.*)?$"
|
|
276
308
|
value = "${{ TICKET_ID }}"
|
|
277
|
-
on-conflict = "error" # optional
|
|
309
|
+
on-conflict = "error" # optional; default: skip
|
|
278
310
|
```
|
|
279
311
|
|
|
280
312
|
Available options:
|
|
281
313
|
|
|
282
|
-
- `skip`
|
|
283
|
-
- `append`
|
|
284
|
-
- `error`
|
|
314
|
+
- `skip` — keep the existing footer and do not add the configured one (default)
|
|
315
|
+
- `append` — keep the existing footer and add the configured one at the end
|
|
316
|
+
- `error` — return an error without writing the formatted message; when running as a hook, this aborts the commit
|
|
285
317
|
|
|
286
318
|
#### Footer formatting
|
|
287
319
|
|
|
288
|
-
You can customize how footers are formatted using `separator` and `alignment
|
|
320
|
+
You can customize how footers are formatted using `separator` and `alignment`. The separator must be a single character.
|
|
289
321
|
|
|
290
322
|
```toml
|
|
291
323
|
[[additional-footers]]
|
|
@@ -297,8 +329,8 @@ alignment = "right"
|
|
|
297
329
|
|
|
298
330
|
Available alignment options:
|
|
299
331
|
|
|
300
|
-
- `left`
|
|
301
|
-
- `right`
|
|
332
|
+
- `left` — no space before the separator and one after it (default): `Ticket-ID# CFMT-123`
|
|
333
|
+
- `right` — one space before the separator and none after it: `Ticket-ID #CFMT-123`
|
|
302
334
|
|
|
303
335
|
### Recipe
|
|
304
336
|
|
|
@@ -321,28 +353,54 @@ case = "upper-first"
|
|
|
321
353
|
breaking-exclamation = true
|
|
322
354
|
```
|
|
323
355
|
|
|
324
|
-
##
|
|
356
|
+
## Modes
|
|
357
|
+
|
|
358
|
+
### Formatting mode
|
|
325
359
|
|
|
326
|
-
|
|
360
|
+
Formatting is the default mode. commitfmt normalizes the message structure and applies fixes from enabled rules. Safe fixes are always applied; unsafe fixes are applied only when [`unsafe-fixes`](#unsafe-fixes) is enabled. An unfixable violation returns a non-zero exit status and prevents the formatted message from being written.
|
|
361
|
+
|
|
362
|
+
When a message is supplied through standard input, `commitfmt` formats it and writes the result to standard output:
|
|
327
363
|
|
|
328
364
|
```bash
|
|
329
|
-
|
|
365
|
+
printf '%s\n' "chore ( test ) : test commit." | commitfmt
|
|
366
|
+
# chore(test): test commit
|
|
367
|
+
|
|
330
368
|
# or
|
|
331
|
-
|
|
369
|
+
commitfmt < commit_text.txt
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
The command exits with a non-zero status if configuration loading, parsing, or an unfixable rule fails.
|
|
373
|
+
|
|
374
|
+
When run without redirected standard input during an active Git commit, as in a `prepare-commit-msg` hook, commitfmt reads and updates Git's `COMMIT_EDITMSG` file instead of writing the formatted message to standard output.
|
|
375
|
+
|
|
376
|
+
### Lint mode
|
|
377
|
+
|
|
378
|
+
Use `--lint` to check a message without modifying it or applying available fixes:
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
printf '%s\n' "chore(test): test commit" | commitfmt --lint
|
|
332
382
|
```
|
|
333
383
|
|
|
334
|
-
|
|
384
|
+
A valid message produces no output and exits with status 0. Any violation produces a report and a non-zero exit status. When used in a hook, lint mode checks `COMMIT_EDITMSG` but never rewrites it.
|
|
335
385
|
|
|
336
|
-
|
|
386
|
+
### History mode
|
|
387
|
+
|
|
388
|
+
Use `--from` to lint a Git commit range:
|
|
337
389
|
|
|
338
390
|
```bash
|
|
339
391
|
commitfmt --from HEAD~20
|
|
340
392
|
# or
|
|
341
|
-
commitfmt --from
|
|
393
|
+
commitfmt --from v1.1.0 --to HEAD
|
|
342
394
|
```
|
|
343
395
|
|
|
396
|
+
The lower boundary is excluded. `--to` defaults to `HEAD` and can only be used together with `--from`. History mode never modifies existing commits and always lints messages, so `--lint` is unnecessary and ignored.
|
|
397
|
+
|
|
344
398
|
## Ignoring commits
|
|
345
399
|
|
|
346
|
-
commitfmt
|
|
400
|
+
commitfmt skips messages whose text starts with the exact, case-sensitive prefix `Merge` or `Revert`. This avoids rewriting Git-generated merge and revert messages.
|
|
401
|
+
|
|
402
|
+
The check is based only on the message text, not commit metadata: `merge`, `revert:`, and other differently cased prefixes are not skipped, while any custom message starting with `Merge` or `Revert` is skipped. This applies both when formatting a single message and when linting history.
|
|
403
|
+
|
|
404
|
+
## License
|
|
347
405
|
|
|
348
|
-
|
|
406
|
+
[MIT](./LICENSE).
|
package/commitfmt.exe
CHANGED
|
Binary file
|