diff options
Diffstat (limited to 'docs/index.md')
-rw-r--r-- | docs/index.md | 339 |
1 files changed, 247 insertions, 92 deletions
diff --git a/docs/index.md b/docs/index.md index 3155b19..b735b6b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -# Intro +# Introduction Gitlint is a git commit message linter written in python: it checks your commit messages for style. Great for use as a [commit-msg git hook](#using-gitlint-as-a-commit-msg-hook) or as part of your gating script in a @@ -7,46 +7,55 @@ Great for use as a [commit-msg git hook](#using-gitlint-as-a-commit-msg-hook) or <script type="text/javascript" src="https://asciinema.org/a/30477.js" id="asciicast-30477" async></script> !!! note - **Gitlint support for Windows is experimental**, and [there are some known issues](https://github.com/jorisroovers/gitlint/issues?q=is%3Aissue+is%3Aopen+label%3Awindows). + **Gitlint works on Windows**, but [there are some known issues](https://github.com/jorisroovers/gitlint/issues?q=is%3Aissue+is%3Aopen+label%3Awindows). Also, gitlint is not the only git commit message linter out there, if you are looking for an alternative written in a different language, have a look at [fit-commit](https://github.com/m1foley/fit-commit) (Ruby), [node-commit-msg](https://github.com/clns/node-commit-msg) (Node.js) or [commitlint](http://marionebl.github.io/commitlint) (Node.js). -## Features ## + +!!! important + **Gitlint requires Python 3.7 (or above). For Python 2.7 and Python 3.5 use `gitlint==0.14.0` (released 2020-10-24), for Python 3.6 `gitlint==0.18.0` (released 2022-11-16).** + +## Features - **Commit message hook**: [Auto-trigger validations against new commit message right when you're committing](#using-gitlint-as-a-commit-msg-hook). Also [works with pre-commit](#using-gitlint-through-pre-commit). - **Easily integrated**: Gitlint is designed to work [with your own scripts or CI system](#using-gitlint-in-a-ci-environment). - **Sane defaults:** Many of gitlint's validations are based on [well-known](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html), -[community](http://addamhardy.com/2013/06/05/good-commit-messages-and-enforcing-them-with-git-hooks.html), +[community](https://addamhardy.com/2013-06-05-good-commit-messages-and-enforcing-them-with-git-hooks), [standards](http://chris.beams.io/posts/git-commit/), others are based on checks that we've found useful throughout the years. - **Easily configurable:** Gitlint has sane defaults, but [you can also easily customize it to your own liking](configuration.md). - - **Community contributed rules**: Conventions that are common but not universal [can be selectively enabled](contrib_rules). + - **Community contributed rules**: Conventions that are common but not universal [can be selectively enabled](contrib_rules.md). - **User-defined rules:** Want to do more then what gitlint offers out of the box? Write your own [user defined rules](user_defined_rules.md). - - **Broad python version support:** Gitlint supports python versions 2.7, 3.5+, PyPy2 and PyPy3.5. - **Full unicode support:** Lint your Russian, Chinese or Emoji commit messages with ease! - **Production-ready:** Gitlint checks a lot of the boxes you're looking for: actively maintained, high unit test coverage, integration tests, - python code standards (pep8, pylint), good documentation, widely used, proven track record. + python code standards ([black](https://github.com/psf/black), [ruff](https://github.com/charliermarsh/ruff)), + good documentation, widely used, proven track record. -# Getting Started -## Installation -```bash +## Getting Started +### Installation +```sh # Pip is recommended to install the latest version pip install gitlint -# macOS -brew tap rockyluke/devops -brew install gitlint +# Alternative: by default, gitlint is installed with pinned dependencies. +# To install gitlint with looser dependency requirements, only install gitlint-core. +pip install gitlint-core -# Ubuntu -apt-get install gitlint +# Community maintained packages: +brew install gitlint # Homebrew (macOS) +sudo port install gitlint # Macports (macOS) +apt-get install gitlint # Ubuntu +# Other package managers, see https://repology.org/project/gitlint/versions # Docker: https://hub.docker.com/r/jorisroovers/gitlint -docker run -v $(pwd):/repo jorisroovers/gitlint +docker run --ulimit nofile=1024 -v $(pwd):/repo jorisroovers/gitlint +# NOTE: --ulimit is required to work around a limitation in Docker +# Details: https://github.com/jorisroovers/gitlint/issues/129 ``` -## Usage +### Usage ```sh # Check the last commit message gitlint @@ -64,7 +73,7 @@ gitlint install-hook ``` Output example: -```bash +```sh $ cat examples/commit-message-2 | gitlint 1: T1 Title exceeds max length (134>80): "This is the title of a commit message that is over 80 characters and contains hard tabs and trailing whitespace and the word wiping " 1: T2 Title has trailing whitespace: "This is the title of a commit message that is over 80 characters and contains hard tabs and trailing whitespace and the word wiping " @@ -77,11 +86,24 @@ $ cat examples/commit-message-2 | gitlint !!! note The returned exit code equals the number of errors found. [Some exit codes are special](index.md#exit-codes). -# Configuration +### Shell completion + +```sh +# Bash: add to ~/.bashrc +eval "$(_GITLINT_COMPLETE=bash_source gitlint)" + +# Zsh: add to ~/.zshrc +eval "$(_GITLINT_COMPLETE=zsh_source gitlint)" + +# Fish: add to ~/.config/fish/completions/foo-bar.fish +eval (env _GITLINT_COMPLETE=fish_source gitlint) +``` + +## Configuration For in-depth documentation of general and rule-specific configuration options, have a look at the [Configuration](configuration.md) and [Rules](rules.md) pages. -Short example ```.gitlint``` file ([full reference](configuration.md)): +Short example `.gitlint` file ([full reference](configuration.md)): ```ini [general] @@ -89,7 +111,7 @@ Short example ```.gitlint``` file ([full reference](configuration.md)): # their id or by their full name ignore=body-is-missing,T3 -# Ignore any data send to gitlint via stdin +# Ignore any data sent to gitlint via stdin ignore-stdin=true # Configure title-max-length rule, set title length to 80 (72 = default) @@ -103,7 +125,7 @@ line-length=123 Example use of flags: -```bash +```sh # Change gitlint's verbosity. $ gitlint -v # Ignore certain rules @@ -129,9 +151,11 @@ Options: current working directory] -C, --config FILE Config file location [default: .gitlint] -c TEXT Config flags in format <rule>.<option>=<value> - (e.g.: -c T1.line-length=80). Flag can be used - multiple times to set multiple config values. - --commits TEXT The range of commits to lint. [default: HEAD] + (e.g.: -c T1.line-length=80). Flag can be + used multiple times to set multiple config values. + --commit TEXT Hash (SHA) of specific commit to lint. + --commits TEXT The range of commits (refspec or comma-separated + hashes) to lint. [default: HEAD] -e, --extra-path PATH Path to a directory or python module with extra user-defined rules --ignore TEXT Ignore rules (comma-separated by id or name). @@ -140,12 +164,14 @@ Options: --msg-filename FILENAME Path to a file containing a commit-msg. --ignore-stdin Ignore any stdin data. Useful for running in CI server. - --staged Read staged commit meta-info from the local - repository. - -v, --verbose Verbosity, more v's for more verbose output (e.g.: - -v, -vv, -vvv). [default: -vvv] - -s, --silent Silent mode (no output). Takes precedence over -v, - -vv, -vvv. + --staged Attempt smart guesses about meta info (like + author name, email, branch, changed files, etc) + for staged commits. + --fail-without-commits Hard fail when the target commit range is empty. + -v, --verbose Verbosity, more v's for more verbose output + (e.g.: -v, -vv, -vvv). [default: -vvv] + -s, --silent Silent mode (no output). + Takes precedence over -v, -vv, -vvv. -d, --debug Enable debugging output. --version Show the version and exit. --help Show this message and exit. @@ -154,19 +180,20 @@ Commands: generate-config Generates a sample gitlint config file. install-hook Install gitlint as a git commit-msg hook. lint Lints a git repository [default command] + run-hook Runs the gitlint commit-msg hook. uninstall-hook Uninstall gitlint commit-msg hook. When no COMMAND is specified, gitlint defaults to 'gitlint lint'. ``` -# Using gitlint as a commit-msg hook ## +## Using gitlint as a commit-msg hook _Introduced in gitlint v0.4.0_ -You can also install gitlint as a git ```commit-msg``` hook so that gitlint checks your commit messages automatically +You can also install gitlint as a git `commit-msg` hook so that gitlint checks your commit messages automatically after each commit. -```bash +```sh gitlint install-hook # To remove the hook gitlint uninstall-hook @@ -174,13 +201,13 @@ gitlint uninstall-hook !!! important - Gitlint cannot work together with an existing hook. If you already have a ```.git/hooks/commit-msg``` - file in your local repository, gitlint will refuse to install the ```commit-msg``` hook. Gitlint will also only + Gitlint cannot work together with an existing hook. If you already have a `.git/hooks/commit-msg` + file in your local repository, gitlint will refuse to install the `commit-msg` hook. Gitlint will also only uninstall unmodified commit-msg hooks that were installed by gitlint. If you're looking to use gitlint in conjunction with other hooks, you should consider [using gitlint with pre-commit](#using-gitlint-through-pre-commit). -# Using gitlint through [pre-commit](https://pre-commit.com) +## Using gitlint through [pre-commit](https://pre-commit.com) `gitlint` can be configured as a plugin for the `pre-commit` git hooks framework. Simply add the configuration to your `.pre-commit-config.yaml`: @@ -198,10 +225,10 @@ pre-commit install --hook-type commit-msg ``` !!! important - It's important that you run ```pre-commit install --hook-type commit-msg```, even if you've already used - ```pre-commit install``` before. ```pre-commit install``` does **not** install commit-msg hooks by default! + It's important that you run `pre-commit install --hook-type commit-msg`, even if you've already used + `pre-commit install` before. `pre-commit install` does **not** install commit-msg hooks by default! -To manually trigger gitlint using ```pre-commit``` for your last commit message, use the following command: +To manually trigger gitlint using `pre-commit` for your last commit message, use the following command: ```sh pre-commit run gitlint --hook-stage commit-msg --commit-msg-filename .git/COMMIT_EDITMSG ``` @@ -211,16 +238,49 @@ In case you want to change gitlint's behavior, you should either use a `.gitlint your `.pre-commit-config.yaml` file like so: ```yaml - repo: https://github.com/jorisroovers/gitlint - rev: # Fill in a tag / sha here + rev: # Fill in a tag / sha here (e.g. v0.18.0) hooks: - id: gitlint - stages: [commit-msg] - entry: gitlint args: [--contrib=CT1, --msg-filename] ``` -# Using gitlint in a CI environment ## -By default, when just running ```gitlint``` without additional parameters, gitlint lints the last commit in the current +!!! important + + You need to add `--msg-filename` at the end of your custom `args` list as the gitlint-hook will fail otherwise. + + +### gitlint and pre-commit in CI +gitlint also supports a `gitlint-ci` pre-commit hook that can be used in CI environments. + +Configure it like so: +```yaml +- repo: https://github.com/jorisroovers/gitlint + rev: # insert ref, e.g. v0.18.0 + hooks: + - id: gitlint # this is the regular commit-msg hook + - id: gitlint-ci # hook for CI environments +``` + +And invoke it in your CI environment like this: + +```sh +pre-commit run --hook-stage manual gitlint-ci +``` + +By default this will only lint the latest commit. +If you want to lint more commits you can modify the `gitlint-ci` hook like so: + +```yaml +- repo: https://github.com/jorisroovers/gitlint + rev: # insert ref, e.g. v0.18.0 + hooks: + - id: gitlint + - id: gitlint-ci + args: [--debug, --commits, mybranch] # enable debug mode, lint all commits in mybranch +``` + +## Using gitlint in a CI environment +By default, when just running `gitlint` without additional parameters, gitlint lints the last commit in the current working directory. This makes it easy to use gitlint in a CI environment (Jenkins, TravisCI, Github Actions, pre-commit, CircleCI, Gitlab, etc). @@ -229,59 +289,76 @@ In fact, this is exactly what we do ourselves: on every commit, This will cause the build to fail when we submit a bad commit message. Alternatively, gitlint will also lint any commit message that you feed it via stdin like so: -```bash +```sh # lint the last commit message git log -1 --pretty=%B | gitlint # lint a specific commit: 62c0519 git log -1 --pretty=%B 62c0519 | gitlint ``` -Note that gitlint requires that you specify ```--pretty=%B``` (=only print the log message, not the metadata), -future versions of gitlint might fix this and not require the ```--pretty``` argument. +Note that gitlint requires that you specify `--pretty=%B` (=only print the log message, not the metadata), +future versions of gitlint might fix this and not require the `--pretty` argument. -## Linting a range of commits ## +## Linting specific commits or branches -_Introduced in gitlint v0.9.0 (experimental in v0.8.0)_ +Gitlint can lint specific commits using `--commit`: +```sh +gitlint --commit 019cf40580a471a3958d3c346aa8bfd265fe5e16 +gitlint --commit 019cf40 # short SHAs work too +gitlint --commit HEAD~2 # as do special references +gitlint --commit mybranch # lint latest commit on a branch +``` -Gitlint allows users to commit a number of commits at once like so: +You can also lint multiple commits using `--commits` (plural): -```bash +```sh # Lint a specific commit range: gitlint --commits "019cf40...d6bc75a" -# You can also use git's special references: -gitlint --commits "origin..HEAD" -# Or specify a single specific commit in refspec format, like so: -gitlint --commits "019cf40^...019cf40" +# Lint all commits on a branch +gitlint --commits mybranch +# Lint all commits that are different between a branch and your main branch +gitlint --commits "main..mybranch" +# Use git's special references +gitlint --commits "origin/main..HEAD" + +# You can also pass multiple, comma separated commit hashes: +gitlint --commits 019cf40,c50eb150,d6bc75a +# These can include special references as well +gitlint --commits HEAD~1,mybranch-name,origin/main,d6bc75a +# You can also lint a single commit with --commits: +gitling --commits 019cf40, ``` -The ```--commits``` flag takes a **single** refspec argument or commit range. Basically, any range that is understood +The `--commits` flag takes a **single** refspec argument or commit range. Basically, any range that is understood by [git rev-list](https://git-scm.com/docs/git-rev-list) as a single argument will work. -Prior to v0.8.1 gitlint didn't support this feature. However, older versions of gitlint can still lint a range or set -of commits at once by creating a simple bash script that pipes the commit messages one by one into gitlint. This -approach can still be used with newer versions of gitlint in case ```--commits``` doesn't provide the flexibility you -are looking for. +Alternatively, you can pass `--commits` a comma-separated list of commit hashes (both short and full-length SHAs work, +as well as special references such as `HEAD` and branch names). +Gitlint will treat these as pointers to **single** commits and lint these in the order you passed. +`--commits` also accepts a single commit SHA with a trailing comma. -```bash -#!/bin/bash +For cases where the `--commits` option doesn't provide the flexibility you need, you can always use a simple shell +script to lint an arbitrary set of commits, like shown in the example below. -for commit in $(git rev-list master); do - commit_msg=$(git log -1 --pretty=%B $commit) - echo "$commit" - echo "$commit_msg" | gitlint +```sh +#!/bin/sh + +for commit in $(git rev-list my-branch); do + echo "Commit $commit" + gitlint --commit $commit echo "--------" done ``` !!! note One downside to this approach is that you invoke gitlint once per commit vs. once per set of commits. - This means you'll incur the gitlint startup time once per commit, making this approach rather slow if you want to - lint a large set of commits. Always use ```--commits``` if you can to avoid this performance penalty. + This means you'll incur the gitlint startup time once per commit, making it rather slow if you want to + lint a large set of commits. Always use `--commits` if you can to avoid this performance penalty. -# Merge, fixup and squash commits ## -_Introduced in gitlint v0.7.0 (merge), v0.9.0 (fixup, squash) and v0.13.0 (revert)_ +## Merge, fixup, squash and revert commits +_Introduced in gitlint v0.7.0 (merge), v0.9.0 (fixup, squash), v0.13.0 (revert) and v0.18.0 (fixup=amend)_ -**Gitlint ignores merge, revert, fixup and squash commits by default.** +**Gitlint ignores merge, revert, fixup, and squash commits by default.** For merge and revert commits, the rationale for ignoring them is that most users keep git's default messages for these commits (i.e *Merge/Revert "[original commit message]"*). @@ -291,28 +368,26 @@ For example, a common case is that *"Merge:"* being auto-prepended triggers a [title-max-length](rules.md#t1-title-max-length) violation. Most users don't want this, so we disable linting on Merge and Revert commits by default. -For [squash](https://git-scm.com/docs/git-commit#git-commit---squashltcommitgt) and [fixup](https://git-scm.com/docs/git-commit#git-commit---fixupltcommitgt) commits, the rationale is that these are temporary +For [squash](https://git-scm.com/docs/git-commit#git-commit---squashltcommitgt) and [fixup](https://git-scm.com/docs/git-commit#git-commit---fixupltcommitgt) (including [fixup=amend](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt---fixupamendrewordltcommitgt)) commits, the rationale is that these are temporary commits that will be squashed into a different commit, and hence the commit messages for these commits are very -short-lived and not intended to make it into the final commit history. In addition, by prepending *"fixup!"* or -*"squash!"* to your commit message, certain gitlint rules might be violated +short-lived and not intended to make it into the final commit history. In addition, by prepending *"fixup!"*, +*"amend!"* or *"squash!"* to your commit message, certain gitlint rules might be violated (e.g. [title-max-length](rules.md#t1-title-max-length)) which is often undesirable. In case you *do* want to lint these commit messages, you can disable this behavior by setting the -general ```ignore-merge-commits```, ```ignore-revert-commits```, ```ignore-fixup-commits``` or -```ignore-squash-commits``` option to ```false``` +general `ignore-merge-commits`, `ignore-revert-commits`, `ignore-fixup-commits`, `ignore-fixup-amend-commits` or +`ignore-squash-commits` option to `false` [using one of the various ways to configure gitlint](configuration.md). -# Ignoring commits ## -_Introduced in gitlint v0.10.0_ +## Ignoring commits -You can configure gitlint to ignore specific commits. +You can configure gitlint to ignore specific commits or parts of a commit. -One way to do this, is to by [adding a gitline-ignore line to your commit message](configuration.md#commit-specific-config). +One way to do this, is by [adding a gitlint-ignore line to your commit message](configuration.md#commit-specific-config). If you have a case where you want to ignore a certain type of commits all-together, you can use gitlint's *ignore* rules. -Here's an example gitlint file that configures gitlint to ignore rules ```title-max-length``` and ```body-min-length``` -for all commits with a title starting with *"Release"*. +Here's a few examples snippets from a `.gitlint` file: ```ini [ignore-by-title] @@ -326,15 +401,95 @@ ignore=title-max-length,body-min-length # Match commits message bodies that have a line that contains 'release' regex=(.*)release(.*) ignore=all + +[ignore-by-author-name] +# Match commits by author name (e.g. ignore all rules when a commit is made by dependabot) +regex=dependabot +ignore=all ``` +If you just want to ignore certain lines in a commit, you can do that using the +[ignore-body-lines](rules.md#i3-ignore-body-lines) rule. + +```ini +# Ignore all lines that start with 'Co-Authored-By' +[ignore-body-lines] +regex=^Co-Authored-By +``` + +!!! warning + + When ignoring specific lines, gitlint will no longer be aware of them while applying other rules. + This can sometimes be confusing for end-users, especially as line numbers of violations will typically no longer + match line numbers in the original commit message. Make sure to educate your users accordingly. + !!! note - Right now it's not possible to write user-defined ignore rules to handle more complex use-cases. - This is however something that we'd like to implement in a future version. If this is something you're interested in - please let us know by [opening an issue](https://github.com/jorisroovers/gitlint/issues). + If you want to implement more complex ignore rules according to your own logic, you can do so using [user-defined + configuration rules](user_defined_rules.md#configuration-rules). + +## Named Rules + +Introduced in gitlint v0.14.0 + +Named rules allow you to have multiple of the same rules active at the same time, which allows you to +enforce the same rule multiple times but with different options. Named rules are so-called because they require an +additional unique identifier (i.e. the rule *name*) during configuration. + +!!! warning + + Named rules is an advanced topic. It's easy to make mistakes by defining conflicting instances of the same rule. + For example, by defining 2 `body-max-line-length` rules with different `line-length` options, you obviously create + a conflicting situation. Gitlint does not do any resolution of such conflicts, it's up to you to make sure + any configuration is non-conflicting. So caution advised! + +Defining a named rule is easy, for example using your `.gitlint` file: + +```ini +# By adding the following section, you will add a second instance of the +# title-must-not-contain-word (T5) rule (in addition to the one that is enabled +# by default) with the name 'extra-words'. +[title-must-not-contain-word:extra-words] +words=foo,bar + +# So the generic form is +# [<rule-id-or-name>:<your-chosen-name>] +# Another example, referencing the rule type by id +[T5:more-words] +words=hur,dur + +# You can add as many additional rules and you can name them whatever you want +# The only requirement is that names cannot contain whitespace or colons (:) +[title-must-not-contain-word:This-Can_Be*Whatever$YouWant] +words=wonderwoman,batman,power ranger +``` + +When executing gitlint, you will see the violations from the default `title-must-not-contain-word (T5)` rule, as well as +the violations caused by the additional Named Rules. + +```sh +$ gitlint +1: T5 Title contains the word 'WIP' (case-insensitive): "WIP: foo wonderwoman hur bar" +1: T5:This-Can_Be*Whatever$YouWant Title contains the word 'wonderwoman' (case-insensitive): "WIP: foo wonderwoman hur bar" +1: T5:extra-words Title contains the word 'foo' (case-insensitive): "WIP: foo wonderwoman hur bar" +1: T5:extra-words Title contains the word 'bar' (case-insensitive): "WIP: foo wonderwoman hur bar" +1: T5:more-words Title contains the word 'hur' (case-insensitive): "WIP: foo wonderwoman hur bar" +``` + +Named rules are further treated identical to all other rules in gitlint: + +- You can reference them by their full name, when e.g. adding them to your `ignore` configuration +```ini +# .gitlint file example +[general] +ignore=T5:more-words,title-must-not-contain-word:extra-words +``` + +- You can use them to instantiate multiple of the same [user-defined rule](user_defined_rules.md) +- You can configure them using [any of the ways you can configure regular gitlint rules](configuration.md) + -# Exit codes ## +## Exit codes Gitlint uses the exit code as a simple way to indicate the number of violations found. Some exit codes are used to indicate special errors as indicated in the table below. @@ -344,8 +499,8 @@ of violations counted by the exit code is 252. Note that gitlint does not have a it can detect, it will just always return with exit code 252 when the number of violations is greater than or equal to 252. -Exit Code | Description ------------|------------------------------------------------------------ -253 | Wrong invocation of the ```gitlint``` command. -254 | Something went wrong when invoking git. -255 | Invalid gitlint configuration +| Exit Code | Description | +| --------- | ------------------------------------------ | +| 253 | Wrong invocation of the `gitlint` command. | +| 254 | Something went wrong when invoking git. | +| 255 | Invalid gitlint configuration | |