### Local setup with hatch Source: https://jorisroovers.com/gitlint/latest/contributing/environment_setup Sets up a local gitlint development environment: clones the repo, creates a virtualenv, installs hatch 1.6.3, and runs gitlint and unit tests via hatch. ```bash # Clone gitlint repo git clone https://github.com/jorisroovers/gitlint cd gitlint # You can choose whether to install hatch in a virtualenv or globally # Either way, hatch will use virtualenvs under-the-hood for gitlint virtualenv .venv && source .venv/bin/activate pip install hatch==1.6.3 # Run gitlint hatch run dev:gitlint --version # # Run unit tests hatch run test:unit-tests # ``` -------------------------------- ### Install and run gitlint Source: https://jorisroovers.com/gitlint/latest/getting_started Install gitlint and run it against the last commit, all commits, a specific commit, a commit message from a file, or a piped commit message. Also installs the commit-msg hook. ```bash # Install gitlint pip install gitlint # # Check the last commit message gitlint # Lint all commits in your repo gitlint --commits HEAD # # 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 # Install gitlint commit-msg hook gitlint install-hook # ``` -------------------------------- ### Install gitlint with pip Source: https://jorisroovers.com/gitlint/latest/installation Installs gitlint with pinned dependencies. This is the recommended installation method. ```bash pip install gitlint ``` -------------------------------- ### ReleaseConfigurationRule example (UCR1) Source: https://jorisroovers.com/gitlint/latest/rules/user_defined_rules/configuration_rules Example configuration rule that modifies gitlint's behavior for commits whose title starts with 'Release'. It appends an ignore rule, sets rule and general options, strips body lines starting with '$', and adds a custom property to the commit object. Use this as a starting point by copying examples/my_configuration_rules.py and adapting it. ```python from gitlint.rules import ConfigurationRule from gitlint.options import IntOption class ReleaseConfigurationRule(ConfigurationRule): """ This rule will modify gitlint's behavior for Release Commits. This example might not be the most realistic for a real-world scenario, but is meant to give an overview of what's possible. """ # A rule MUST have a human friendly name name = "release-configuration-rule" # A rule MUST have a *unique* id # We recommend starting with UCR (for User-defined Configuration-Rule) id = "UCR1" # A rule MAY have an option_spec if its behavior should be configurable. options_spec = [ IntOption("custom-verbosity", 2, "Verbosity for release commits"), ] def apply(self, config, commit): self.log.debug("This will be visible when running `gitlint --debug`") # If the commit title starts with 'Release', we want to modify # how all subsequent rules interpret that commit if commit.message.title.startswith("Release"): # If your Release commit messages are auto-generated, the # body might contain trailing whitespace. Let's ignore that config.ignore.append("body-trailing-whitespace") # Similarly, the body lines might exceed 80 chars, # let's set gitlint's limit to 99 # To set rule options use: # config.set_rule_option(, , ) config.set_rule_option("body-max-line-length", "line-length", 99) # For kicks, let's set gitlint's verbosity to 2 # To set general options use # config.set_general_option(, ) config.set_general_option("verbosity", 2) # We can also use custom options to make this configurable custom_verbosity = self.options["custom-verbosity"].value config.set_general_option("verbosity", custom_verbosity) # Strip any lines starting with $ from the commit message # (this only affects how gitlint sees your commit message, # it does NOT modify your actual commit in git) body = [l for l in commit.message.body if not l.startswith("$")] commit.message.body = body # You can add any extra properties you want to the commit object, # these will be available later on in all rules. commit.my_property = "This is my property" ``` -------------------------------- ### Run gitlint with extra-path examples Source: https://jorisroovers.com/gitlint/latest/rules/user_defined_rules Example command that pipes a commit message into gitlint with the extra-path option pointing to the examples directory, showing the output of a user-defined rule violation. ```bash $ cat examples/commit-message-1 | gitlint --extra-path examples/ 1: UC2 Body does not contain a 'Signed-off-by Line' # ``` -------------------------------- ### Example .gitlint configuration file Source: https://jorisroovers.com/gitlint/latest/configuration/gitlint_file A complete example .gitlint file showing general configuration, rule overrides, named rules, contrib rules, user-defined rules, and ignore rules. It includes settings for ignoring commits, regex matching, and custom rule parameters. ```ini ### GENERAL CONFIG ### [general] # Ignore rules, reference them by id or name (comma-separated) ignore=title-trailing-punctuation, T3 # verbosity should be a value between 1 and 3 verbosity = 2 # By default gitlint will ignore certain commits ignore-merge-commits=true ignore-revert-commits=true ignore-fixup-commits=true ignore-fixup-amend-commits=true ignore-squash-commits=true # Ignore any data sent to gitlint via stdin ignore-stdin=true # Fetch additional meta-data from the local repository when manually passing a # commit message to gitlint via stdin or --commit-msg. Disabled by default. staged=true # Hard fail when the target commit range is empty. fail-without-commits=true # # Whether to use Python `search` instead of `match` semantics in rules regex-style-search=true # Enable community contributed rules contrib=contrib-title-conventional-commits,CC1 # # Set the extra-path where gitlint will search for user defined rules # extra-path=examples/ ### RULE CONFIGURATION ### [title-max-length] line-length=80 [title-min-length] min-length=5 [title-must-not-contain-word] # Comma-separated list of words that should not occur in # the commit message title (case-insensitive). words=wip,foobar [title-match-regex] regex=^US[0-9]* # [body-max-line-length] line-length=120 [body-min-length] min-length=5 [body-is-missing] # Ignore this rule on merge commits (default=true) # ignore-merge-commits=false [body-changed-file-mention] # Files that need to be explicitly mentioned in the body when they change files=gitlint-core/gitlint/rules.py,README.md # [body-match-regex] regex=My-Commit-Tag: foo$ # [author-valid-email] # E.g.: Only allow email addresses from foo.com regex=[^@]+@foo.com # ### NAMED RULES ### [title-must-not-contain-word:Additional-Words] words=foo,bar ### CONTRIB RULES ### [contrib-title-conventional-commits] types = bugfix,user-story,epic ### USER DEFINED RULES ### [body-max-line-count] max-line-count = 5 ### IGNORE RULES CONFIGURATION ### [ignore-by-title] # Ignore rules for commits of which the title matches a regex regex=^Release(.*) # ignore=T1,body-min-length # [ignore-by-body] # Ignore rules for commits of which the body has a line that matches a regex regex=(.*)release(.*) # ignore=T1,body-min-length [ignore-body-lines] # Ignore all lines that start with 'Co-Authored-By' regex=^Co-Authored-By # [ignore-by-author-name] regex=(.*)dependabot(.*) # ignore=T1,body-min-length ``` -------------------------------- ### Install gitlint-core with pip Source: https://jorisroovers.com/gitlint/latest/installation Installs only gitlint-core, which has looser dependency requirements. Use this if you prefer less strict dependency pinning. ```bash pip install gitlint-core ``` -------------------------------- ### Install pre-commit commit-msg hook Source: https://jorisroovers.com/gitlint/latest/commit_hooks Install the pre-commit hook with the commit-msg type. This command is required even if `pre-commit install` was already run, because that command does not install commit-msg hooks by default. ```bash pre-commit install --hook-type commit-msg ``` -------------------------------- ### Install gitlint with apt-get Source: https://jorisroovers.com/gitlint/latest/installation Installs gitlint via apt-get on Ubuntu. This package is community-maintained and not officially supported. ```bash apt-get install gitlint ``` -------------------------------- ### Install gitlint with Homebrew Source: https://jorisroovers.com/gitlint/latest/installation Installs gitlint via Homebrew. This package is community-maintained and not officially supported. ```bash brew install gitlint ``` -------------------------------- ### .gitlint configuration file Source: https://jorisroovers.com/gitlint/latest/configuration Example .gitlint configuration file showing general settings and rule configuration. Rules can be referenced by full name or id (e.g., [title-max-length] or [T1]). ```ini [general] # Ignore rules, reference them by id or name (comma-separated) ignore=title-trailing-punctuation, T3 # Enable specific community contributed rules contrib=contrib-title-conventional-commits,CC1 # Set the extra-path where gitlint will search for user defined rules extra-path=./gitlint_rules/my_rules.py ### Configuring rules ### Configure the behavior of a specific rule by adding a section for it to the ini file. Rules can be referenced by their full name or by id. For example, the rule [title-max-length] could also be referenced as [T1]. [T1] line-length=80 ``` -------------------------------- ### Install additional Python versions with asdf Source: https://jorisroovers.com/gitlint/latest/contributing/environment_setup Installs additional Python versions in the dev container using asdf, sets the global version, installs hatch for that version, and prunes the hatch environment before running other commands. ```bash # Ensure ASDF overrides system python in PATH # You can also append this line to your ~/.bash_profile in the devcontainer to have this happen automatically on login source "$(brew --prefix asdf)/libexec/asdf.sh" # Install python 3.9.15 asdf install python 3.9.15 # Make python 3.9.15 the default python asdf global python 3.9.15 # IMPORTANT: install hatch for this python version pip install hatch==1.6.3 # You also need to prune your hatch environment first before running other commands hatch env prune # List all available python versions asdf list all python # List installed python versions asdf list python ``` -------------------------------- ### Install and uninstall gitlint commit-msg hook Source: https://jorisroovers.com/gitlint/latest/commit_hooks Install gitlint as a commit-msg hook in the current repository. Use `gitlint uninstall-hook` to remove it. Gitlint refuses to install if a `.git/hooks/commit-msg` file already exists and only uninstalls unmodified hooks it installed. ```bash gitlint install-hook # Remove the hook gitlint uninstall-hook ``` -------------------------------- ### Install a specific gitlint dev build from PyPI Source: https://jorisroovers.com/gitlint/latest/contributing/releases Use pip to install a specific dev build version of gitlint, replacing the version number with the latest from https://pypi.org/project/gitlint/#history. Note that installation can fail for a few minutes after a new version appears due to PyPI mirror replication. ```bash # Find latest dev build on https://pypi.org/project/gitlint/#history pip install gitlint=="0.19.0.dev68" ``` -------------------------------- ### Install gitlint with MacPorts Source: https://jorisroovers.com/gitlint/latest/installation Installs gitlint via MacPorts. This package is community-maintained and not officially supported. ```bash port install gitlint ``` -------------------------------- ### Gitlint output with named rules Source: https://jorisroovers.com/gitlint/latest/rules/named_rules Example output from running gitlint with the named rules defined above, showing violations from both the default rule and the named instances. ```text $ 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" ``` -------------------------------- ### Configure contrib-title-conventional-commits types Source: https://jorisroovers.com/gitlint/latest/rules/contrib_rules Configuration example for the contrib-title-conventional-commits rule, setting the types option. ```ini [contrib-title-conventional-commits] line-length=bugfix,user-story,epic ``` -------------------------------- ### gitlint output example Source: https://jorisroovers.com/gitlint/latest/getting_started Example output from running gitlint on a commit message file. Shows rule violations with line numbers and rule IDs (T1, T2, T4, B1, B2, B3, B4). The exit code equals the number of errors found, with some special exit codes. ```bash $ 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 " 1: T4 Title contains hard tab characters (\t): "This is the title of a commit message that is over 80 characters and contains hard tabs and trailing whitespace and the word wiping " 2: B4 Second line is not empty: "This line should not contain text" 3: B1 Line exceeds max length (125>80): "Lines typically need to have a max length, meaning that they can't exceed a preset number of characters, usually 80 or 120. " 3: B2 Line has trailing whitespace: "Lines typically need to have a max length, meaning that they can't exceed a preset number of characters, usually 80 or 120. " 3: B3 Line contains hard tab characters (\t): "Lines typically need to have a max length, meaning that they can't exceed a preset number of characters, usually 80 or 120. " ``` -------------------------------- ### gitlint output with contrib rules Source: https://jorisroovers.com/gitlint/latest/rules/contrib_rules Example output when running gitlint with contrib rules enabled, showing violations for CC1 and CL1. ```bash $ 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." ``` -------------------------------- ### Ignore named rules via .gitlint configuration Source: https://jorisroovers.com/gitlint/latest/rules/named_rules Configuration example showing how to ignore named rules by referencing their full names in the [general] ignore setting. ```ini [general] ignore=T5:more-words,title-must-not-contain-word:extra-words ``` -------------------------------- ### Ignore named rules via CLI flag Source: https://jorisroovers.com/gitlint/latest/rules/named_rules Command-line example showing how to ignore named rules using the --ignore flag. ```bash gitlint --ignore="T5:more-words,title-must-not-contain-word:extra-words" ``` -------------------------------- ### Define named rules in .gitlint Source: https://jorisroovers.com/gitlint/latest/rules/named_rules Configuration example showing how to add additional instances of the title-must-not-contain-word (T5) rule with custom names and words. Note that gitlint does not resolve conflicts between multiple instances. ```ini # By adding the following section, you will add a second instance of the # title-must-not-contain-word (T5) rule, with the name 'extra-words' [title-must-not-contain-word:extra-words] words=foo,bar # 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 [title-must-not-contain-word:This-Can_Be*Whatever$YouWant] words=wonderwoman,batman,power ranger ``` -------------------------------- ### Use different option types in options_spec Source: https://jorisroovers.com/gitlint/latest/rules/user_defined_rules/options Illustrates the various option types available from gitlint.options: StrOption, IntOption, BoolOption, ListOption, PathOption, and RegexOption. Note the ListOption example appears to have a syntax error in the source. ```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"), ] ``` -------------------------------- ### User-defined CommitRule example Source: https://jorisroovers.com/gitlint/latest/rules/user_defined_rules Example of a user-defined CommitRule that enforces a 'Signed-off-by' line in the commit body. The rule must have a name and a unique id (recommended to start with UC). The validate method returns a RuleViolation if the condition is not met. ```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)] ``` -------------------------------- ### Serve documentation locally with mkdocs Source: https://jorisroovers.com/gitlint/latest/contributing/tests_formatting_docs Serve the documentation locally with mkdocs and Material for MkDocs. Access the website at http://localhost:8000. ```bash hatch run docs:serve ``` -------------------------------- ### Configure title-match-regex in .gitlint Source: https://jorisroovers.com/gitlint/latest/rules/builtin_rules Configure the T7 rule to require titles to match a custom regex. The example sets the regex to match a user-story identifier starting with 'US' followed by a digit. ```ini # Ensure every title starts with a user-story identifier like US123 [title-match-regex] regex=^US[1-9][0-9]* ``` -------------------------------- ### gitlint --help output Source: https://jorisroovers.com/gitlint/latest/configuration/cli Full reference of all gitlint commands and options. Shows default values, available commands (generate-config, install-hook, lint, run-hook, uninstall-hook), and that gitlint defaults to 'gitlint lint' when no command is specified. ```bash $ 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 .