### 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 .