### Install Gitlint with Pip
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/installation.md
Install gitlint using pip for standard installation with pinned dependencies. This is the recommended method.
```sh
pip install gitlint
```
--------------------------------
### Test Gitlint Release Installation
Source: https://github.com/jorisroovers/gitlint/wiki/[ARCHIVE]-Release-MOP
This script sets up a clean virtual environment, installs the gitlint package, and performs basic manual tests to verify the installation and functionality.
```sh
# Set release variable for the next steps
export RELEASE_VERSION=`python -c "import gitlint; print(gitlint.__version__)"`; export GITLINT_DIR=`pwd`; export GITLINT_TEST_DIR="/tmp/release-$RELEASE_VERSION"
echo -e "RELEASE_VERSION: $RELEASE_VERSION\nGITLINT_DIR: $GITLINT_DIR\nGITLINT_TEST_DIR: $GITLINT_TEST_DIR"
deactivate # deactivate current virtualenv
# Create virtualenv to test the release
mkdir $GITLINT_TEST_DIR && cd $GITLINT_TEST_DIR
virtualenv -p /usr/bin/python3.8 .venv38 && source .venv38/bin/activate
# Install
gitlint # should not work
pip install --no-cache-dir gitlint # no-cache-dir to disable caching (otherwise pip doesn't always find the new package)
# Do some basic manual testing
cd $GITLINT_TEST_DIR
gitlint --version # should print the correct version
rm -rf foo && git init foo && cd foo
git config user.email foo@bar.com && git config user.name "John Doe"
git commit --allow-empty -m "WIP: föo"
gitlint
# Expected:
# 1: T5 Title contains the word 'WIP' (case-insensitive): "WIP: föo"
# 3: B6 Body message is missing
gitlint --debug
# Check version at the top, python version
echo "WIP: föo2" | gitlint
# Expected:
# 1: T5 Title contains the word 'WIP' (case-insensitive): "WIP: föo2"
# 3: B6 Body message is missing
echo "föo3" | gitlint -c title-max-length.line-length=2
# Expected:
# 1: T1 Title exceeds max length (4>2): "föo3"
# 1: T8 Title is too short (4<5): "föo3"
# 3: B6 Body message is missing
gitlint install-hook
git commit --allow-empty -m "WIP: föo4"
# Run integration tests
pip install -r $GITLINT_DIR/qa/requirements.txt
pushd $GITLINT_DIR && ./run_tests.sh -i && popd
# Cleanup
deactivate; cd $GITLINT_DIR && rm -rf $GITLINT_TEST_DIR
```
--------------------------------
### Test Package Installation and Basic Functionality
Source: https://github.com/jorisroovers/gitlint/wiki/[ARCHIVE]-Release-MOP
This script sets up a temporary directory, creates a virtual environment, installs gitlint from test.pypi.org, and performs basic version checks and commit message linting tests.
```shell
# Set release variable for the next steps
export RELEASE_VERSION=`python -c "import gitlint; print(gitlint.__version__)"`; export GITLINT_DIR=`pwd`; export GITLINT_TEST_DIR="/tmp/release-test-$RELEASE_VERSION"
echo -e "RELEASE_VERSION: $RELEASE_VERSION\nGITLINT_DIR: $GITLINT_DIR\nGITLINT_TEST_DIR: $GITLINT_TEST_DIR"
deactivate # deactivate current virtualenv
# Create virtualenv to test the release
mkdir $GITLINT_TEST_DIR && cd $GITLINT_TEST_DIR
# Python 3.8:
virtualenv -p /usr/bin/python3.8 .venv38 && source .venv38/bin/activate
# Install (make sure the virtualenv of the new release is active)
gitlint # should not work
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple gitlint
pip freeze
# Do some basic manual testing
cd $GITLINT_TEST_DIR
gitlint --version # should print the correct version
rm -rf foo && git init foo && cd foo
git config user.email foo@bar.com && git config user.name "John Doe"
git commit --allow-empty -m "WIP: föo"
gitlint
# Expected:
# 1: T5 Title contains the word 'WIP' (case-insensitive): "WIP: föo"
# 3: B6 Body message is missing
gitlint --debug
# Check version at the top, python version
echo "WIP: föo2" | gitlint
# Expected:
# 1: T5 Title contains the word 'WIP' (case-insensitive): "WIP: föo2"
# 3: B6 Body message is missing
echo "föo3" | gitlint -c title-max-length.line-length=2
# Expected:
# 1: T1 Title exceeds max length (4>2): "föo3"
# 1: T8 Title is too short (4<5): "föo3"
# 3: B6 Body message is missing
gitlint install-hook
git commit --allow-empty -m "WIP: föo4"
# Run integration tests
pip install -r $GITLINT_DIR/qa/requirements.txt
pushd $GITLINT_DIR && ./run_tests.sh -i && popd
# Cleanup
deactivate; cd $GITLINT_DIR && rm -rf $GITLINT_TEST_DIR
```
--------------------------------
### Install Gitlint from TestPyPI
Source: https://github.com/jorisroovers/gitlint/wiki/[ARCHIVE]-Release-MOP--Hatch
Install the specified gitlint version from the test PyPI repository, with a fallback to the main PyPI.
```sh
pip install --no-cache -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple gitlint==$GITLINT_RELEASE_VERSION
```
--------------------------------
### Install Gitlint-Core from Git Archive URL
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/contributing/releases.md
Install gitlint-core directly from a GitHub source Git archive URL using a specific commit hash. This method supports installing unmerged commits (pending PRs).
```sh
# Set commit hash to install
export COMMIT_HASH="345414171baea56c5b2b8290f17a2a13a685274c"
# Install using pinned dependencies
pip install "gitlint-core [trusted-deps] @ https://github.com/jorisroovers/gitlint/archive/$COMMIT_HASH.tar.gz#subdirectory=gitlint-core"
# Install using looser dependencies
pip install "https://github.com/jorisroovers/gitlint/archive/$COMMIT_HASH.tar.gz#subdirectory=gitlint-core"
```
--------------------------------
### Install Gitlint with Apt-get
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/installation.md
Install gitlint on Ubuntu or Debian-based systems using the apt-get package manager.
```sh
apt-get install gitlint
```
--------------------------------
### Install Gitlint with Brew
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/installation.md
Install gitlint on macOS using the Homebrew package manager.
```sh
brew install gitlint
```
--------------------------------
### Run Integration Tests with Installed Gitlint
Source: https://github.com/jorisroovers/gitlint/wiki/[ARCHIVE]-Release-MOP--Hatch
Remove the qa environment, attempt integration tests (expected to fail without gitlint), install gitlint from test PyPI, and then run integration tests again.
```sh
hatch env remove qa
hatch run qa:integration-tests # This must fail since no gitlint installed
hatch run qa:pip install --no-cache -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple gitlint==$GITLINT_RELEASE_VERSION
hatch run qa:integration-tests
```
--------------------------------
### Configure Rule Option via .gitlint
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/rules/user_defined_rules/options.md
Example of configuring a rule option using a `.gitlint` configuration file.
```ini
[body-max-line-count]
max-line-count=1
```
--------------------------------
### Install Gitlint-core with Pip
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/installation.md
Install only the gitlint-core package with pip to use looser dependency requirements.
```sh
pip install gitlint-core
```
--------------------------------
### Install Gitlint from GitHub Source (Looser Dependencies)
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/installation.md
Install gitlint from a GitHub source archive URL using pip, with looser dependency requirements. Ensure the GITLINT_VERSION environment variable is set.
```sh
# Set version to install
export GITLINT_VERSION="v0.20.0"
# Install using looser dependencies
pip install "https://github.com/jorisroovers/gitlint/archive/$GITLINT_VERSION.tar.gz#subdirectory=gitlint-core"
```
--------------------------------
### Install Gitlint with MacPorts
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/installation.md
Install gitlint on macOS using the MacPorts package manager.
```sh
port install gitlint
```
--------------------------------
### Install Gitlint and Test with a Bad Commit Message
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/index.md
This snippet shows how to install gitlint using pip and then create a bad commit message to test gitlint's output. It demonstrates the typical workflow for using gitlint.
```bash
pip install gitlint
# Add a bad commit message
git commit --allow-empty -m " WIP: My bad commit title." -m "who cares "
[main a9f9368] WIP: My bad commit title.
# Run gitlint!
gitlint
```
```bash
1: T3 Title has trailing punctuation (.): " WIP: My bad commit title."
1: T5 Title contains the word 'WIP' (case-insensitive): " WIP: My bad commit title."
1: T6 Title has leading whitespace: " WIP: My bad commit title."
3: B2 Line has trailing whitespace: "who cares "
3: B3 Line contains hard tab characters (\t): "who cares "
3: B5 Body message is too short (10<20): "who cares "
```
--------------------------------
### Install Gitlint from GitHub Source (Pinned Dependencies)
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/installation.md
Install gitlint from a GitHub source archive URL using pip, with pinned dependencies. Ensure the GITLINT_VERSION environment variable is set.
```sh
# Set version to install
export GITLINT_VERSION="v0.20.0"
# Install using pinned dependencies
pip install "gitlint-core [trusted-deps] @ https://github.com/jorisroovers/gitlint/archive/$GITLINT_VERSION.tar.gz#subdirectory=gitlint-core"
```
--------------------------------
### Example Gitlint Output with Contrib Rules
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/rules/contrib_rules.md
This example demonstrates the output of gitlint when certain contrib rules are active and violated. It shows specific rule IDs and violation messages.
```sh
$ gitlint
1: CC1 Body does not contain a 'Signed-off-by' line
1: CL1 Title does not start with one of fix, feat, chore, docs, style, refactor, perf, test: "WIP: This is the title of a commit message."
```
--------------------------------
### Define a Rule with Multiple Options
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/rules/user_defined_rules/options.md
Example demonstrating how to define a rule with multiple options, including integer and boolean types.
```python
options_spec = [
IntOption("max-lint-count", 3, "Maximum body line count"),
BoolOption("count-signoff-by", True, "Include 'Sign-off By' lines in count"),
# etc
]
```
--------------------------------
### Install Gitlint Dev Build
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/contributing/releases.md
Install a development build of gitlint by specifying a dev build version. Find the latest dev build version on the PyPI history page.
```sh
# Find latest dev build on https://pypi.org/project/gitlint/#history
pip install gitlint=="0.19.0.dev68"
```
--------------------------------
### Configure Title Regex Matching
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/rules/builtin_rules.md
Use this snippet to enforce a specific regex pattern for commit message titles. The example ensures titles start with a user-story identifier.
```ini
# Ensure every title starts with a user-story identifier like US123
[title-match-regex]
regex=^US[1-9][0-9]*
```
--------------------------------
### Configure Rule Option via CLI
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/rules/user_defined_rules/options.md
Example of configuring a rule option using the gitlint command-line interface.
```sh
gitlint -c body-max-line-count.max-line-count=1
```
--------------------------------
### Get and Echo Gitlint Release Version
Source: https://github.com/jorisroovers/gitlint/wiki/[ARCHIVE]-Release-MOP--Hatch
Retrieve the current release version using Hatch and display it.
```sh
export GITLINT_RELEASE_VERSION=$(hatch version); echo $GITLINT_RELEASE_VERSION
```
--------------------------------
### Install and Use Gitlint
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/getting_started.md
Install gitlint using pip and use it to check commit messages. Supports checking the last commit, all commits in a repo, specific commits, commit messages from files, and piped commit messages.
```sh
# Install gitlint
pip install gitlint # (1)
# Check the last commit message
gitlint
# Lint all commits in your repo
gitlint --commits HEAD # (2)
# Lint specific single commit
gitlint --commit abc123
# Read the commit-msg from a file
gitlint --msg-filename examples/commit-message-2
# Pipe a commit message to gitlint
git log -1 --pretty=%B | gitlint
```
```sh
# Install gitlint commit-msg hook
gitlint install-hook # (3)
```
--------------------------------
### Define a Rule with Various Option Types
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/rules/user_defined_rules/options.md
Example showcasing the definition of a rule with multiple option types including string, integer, boolean, list, path, and regex.
```python
options_spec = [
StrOption("my-str-option", "default", "Fancy string option"),
IntOption("my-int-option", 3, "Fancy integer option", allow_negative=True),
BoolOption("my-bool-option", False, "Fancy boolean option"),
ListOption("my-list-option"), ["foo", "bar"], "Fancy list option"
PathOption("my-regex-option", "/foo/bar", "Fancy path option", type="dir"),
RegexOption("my-regex-option", "^(foo|bar)", "Fancy regex option"),
]
```
--------------------------------
### Define a Configurable Commit Rule
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/rules/user_defined_rules/options.md
Example of a `CommitRule` with an `IntOption` for maximum body line count. This allows users to configure the maximum number of lines allowed in the commit body.
```python
from gitlint.rules import CommitRule
from gitlint.options import IntOption
class BodyMaxLineCount(CommitRule):
# A rule MUST have a human friendly name
name = "body-max-line-count"
# A rule MUST have a *unique* id
# we recommend starting with UC (for User-defined Commit-rule).
id = "UC1"
# A rule MAY have an option_spec if its behavior is configurable.
options_spec = [
IntOption(
"max-line-count", # option name
3, # default value
"Maximum body line count", # description
)
]
def validate(self, commit):
line_count = len(commit.message.body)
max_count = self.options["max-line-count"].value
if line_count > max_count:
msg = f"Body has too many lines ({line_count} > {max_count})"
return [RuleViolation(self.id, msg, line_nr=1)]
```
--------------------------------
### Implement CommitRule Validation in Python
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/rules/user_defined_rules/violations.md
This example shows a typical `validate` method for a `CommitRule`. It iterates through the commit body, checks for a specific string, and returns a `RuleViolation` if found.
```python
def validate(self, commit)
for line_nr, line in commit.message.body:
if "Jon Snow" in line:
# Add 1 to the line_nr to offset the title which is on the first line
violation_line_nr = line_nr + 1
msg = "Commit message has the words 'Jon Snow' in it"
return [RuleViolation(self.id, msg, line, violation_line_nr)]
return []
```
--------------------------------
### Example commit message violation output
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/rules/user_defined_rules/index.md
Illustrates the output when a commit message violates a user-defined rule, specifically the 'Signed-off-by' rule (UC2).
```sh
$ cat examples/commit-message-1 | gitlint --extra-path examples/
1: UC2 Body does not contain a 'Signed-off-by Line' # (1)
```
--------------------------------
### Gitlint Output with Named Rules
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/rules/named_rules.md
Example output from gitlint showing violations from both default and named instances of the 'title-must-not-contain-word' rule.
```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"
```
--------------------------------
### Example User-Defined Rule: SignedOffBy
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/rules/user_defined_rules/index.md
A Python class implementing a custom gitlint commit rule that checks for the presence of a 'Signed-off-by' line in the commit body. This rule is identified by 'UC2'.
```python
from gitlint.rules import CommitRule, RuleViolation
class SignedOffBy(CommitRule):
"""Enforce that each commit contains a "Signed-off-by" line.
We keep things simple here and just check whether the commit body
contains a line that starts with "Signed-off-by".
"""
# A rule MUST have a human friendly name
name = "body-requires-signed-off-by"
# A rule MUST have a *unique* id
# We recommend starting with UC (for User-defined Commit-rule).
id = "UC2"
def validate(self, commit):
log_msg = "This will be visible when running `gitlint --debug`"
self.log.debug(log_msg)
for line in commit.message.body:
if line.startswith("Signed-off-by"):
return
msg = "Body does not contain a 'Signed-off-by' line"
return [RuleViolation(self.id, msg, line_nr=1)]
```
--------------------------------
### Configure Minimum Title Length
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/rules/builtin_rules.md
Use this snippet to set a minimum character length for commit message titles. The example enforces a minimum length of 3 characters.
```ini
# Titles should be min 3 chars
[title-min-length]
min-length=3
```
--------------------------------
### Gitlint Help Command
Source: https://github.com/jorisroovers/gitlint/blob/main/docs/configuration/cli.md
Display all available commands and options for gitlint, including general options, configuration flags, and specific commands.
```no-highlight
$ gitlint --help
Usage: gitlint [OPTIONS] COMMAND [ARGS]...
Git lint tool, checks your git commit messages for styling issues
Documentation: https://jorisroovers.github.io/gitlint
Options:
--target DIRECTORY Path of the target git repository. [default:
current working directory]
-C, --config FILE Config file location [default: .gitlint]
-c TEXT Config flags in format .