{"id":79428,"date":"2026-10-20T04:51:26","date_gmt":"2026-10-20T04:51:26","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=79428"},"modified":"2026-10-20T04:51:30","modified_gmt":"2026-10-20T04:51:30","slug":"how-to-install-and-configure-pre-commit-on-macos-windows-and-linux-complete-step-by-step-guide","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/how-to-install-and-configure-pre-commit-on-macos-windows-and-linux-complete-step-by-step-guide\/","title":{"rendered":"How to Install and Configure pre-commit on macOS, Windows, and Linux: Complete Step-by-Step Guide"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><strong>SEO Title:<\/strong> How to Install and Configure pre-commit on Mac, Windows &amp; Linux (2026)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Meta Description:<\/strong> Learn how to install and configure pre-commit Git hooks on macOS, Windows, Ubuntu, Debian, and RHEL. Includes installation commands, YAML configuration, automatic linting, formatting, CI\/CD integration, and troubleshooting.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Focus Keywords:<\/strong> pre-commit installation, install pre-commit macOS, pre-commit Windows, pre-commit Ubuntu, pre-commit Linux, pre-commit Git hooks, pre-commit config YAML, pre-commit Terraform, pre-commit Python, pre-commit GitHub Actions<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">1. Introduction<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Writing clean, secure, and maintainable code is an essential part of modern software development.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">However, even experienced developers occasionally introduce issues such as trailing whitespace, incorrectly formatted code, invalid YAML files, debugging statements, oversized files, or accidentally committed credentials.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Finding these issues during code review or after merging changes can waste valuable development time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is where <strong>pre-commit<\/strong> becomes useful.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">pre-commit is an open-source framework for managing Git hooks that automatically checks your code before a commit is created.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It can run formatting tools, linters, configuration validators, and security-related checks without requiring developers to manually execute each tool.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, when a developer executes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">git commit -m <span class=\"hljs-string\">\"Add new feature\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">pre-commit can automatically:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Remove trailing whitespace.<\/li>\n\n\n\n<li>Fix missing end-of-file newlines.<\/li>\n\n\n\n<li>Validate YAML, JSON, and TOML files.<\/li>\n\n\n\n<li>Check for unresolved Git merge conflicts.<\/li>\n\n\n\n<li>Identify certain accidentally included private keys.<\/li>\n\n\n\n<li>Prevent unexpectedly large files from being committed.<\/li>\n\n\n\n<li>Format Python or Terraform files when suitable hooks are configured.<\/li>\n\n\n\n<li>Run additional code-quality checks.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In this tutorial, we will install and configure pre-commit across macOS, Windows, and Linux, build a practical Git hook configuration, and integrate it into everyday development workflows.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. What Is pre-commit?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">pre-commit is a framework that manages and executes Git hooks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Git hooks are scripts that run automatically when specific Git operations occur.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The most common example is the <code>pre-commit<\/code> hook, which runs before Git finalizes a commit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Instead of maintaining custom scripts individually, pre-commit lets developers describe their required checks in a single configuration file:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.pre-commit-config<\/span><span class=\"hljs-selector-class\">.yaml<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The framework downloads supported hooks, creates isolated environments, and executes those hooks against applicable files.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How pre-commit Works<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">Developer changes files\n         |\n         v\n    git add files\n         |\n         v\n      git commit\n         |\n         v\n  Git pre-commit hook\n         |\n         v\n  pre-commit framework\n         |\n         v\n  Execute configured checks\n         |\n     +---+---+\n     |       |\n    PASS    FAIL\n     |       |\n     v       v\n Commit    Commit blocked\n created   Fix errors\n                |\n                v\n           Stage changes\n                |\n                v\n           Retry commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Some hooks only report issues, while others automatically modify files to fix problems.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If a hook modifies a file, you generally need to stage the changes again before committing.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Why Use pre-commit?<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>Without pre-commit<\/th><th>With pre-commit<\/th><\/tr><tr><td>Developers manually run formatting commands<\/td><td>Formatting runs automatically<\/td><\/tr><tr><td>Invalid configuration may reach code review<\/td><td>Syntax errors can be detected before committing<\/td><\/tr><tr><td>Inconsistent coding styles<\/td><td>Consistent checks across contributors<\/td><\/tr><tr><td>More avoidable code-review comments<\/td><td>Many simple issues are corrected locally<\/td><\/tr><tr><td>Each developer maintains separate scripts<\/td><td>Shared configuration in Git<\/td><\/tr><tr><td>Accidental mistakes reach CI\/CD<\/td><td>Many errors are caught earlier<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Important:<\/strong> pre-commit is not a replacement for automated tests, code reviews, security scanning, or CI\/CD pipelines. It provides an additional layer of checks earlier in the development lifecycle.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">3. Prerequisites<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before installing pre-commit, ensure your system has the following components.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>Requirement<\/th><th>Description<\/th><\/tr><tr><td>Operating system<\/td><td>macOS, Windows, or Linux<\/td><\/tr><tr><td>Git<\/td><td>Required for Git hook integration<\/td><\/tr><tr><td>Python<\/td><td>Python 3.11 or newer for pre-commit 4.7.0<\/td><\/tr><tr><td>Internet<\/td><td>Required to download packages and hook dependencies<\/td><\/tr><tr><td>Terminal<\/td><td>Bash, Zsh, PowerShell, or compatible terminal<\/td><\/tr><tr><td>Git repository<\/td><td>Required for installing project-specific hooks<\/td><\/tr><tr><td>Package manager<\/td><td>Homebrew, pipx, pip, or another supported method<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">pre-commit itself requires Python, but it can manage hooks written in many programming languages.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Check Git Installation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">On macOS or Linux:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">git --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">On Windows PowerShell:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">git --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Example output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">git<\/span> <span class=\"hljs-selector-tag\">version<\/span> 2<span class=\"hljs-selector-class\">.x<\/span><span class=\"hljs-selector-class\">.x<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If Git is missing, install it from:<\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/git-scm.com\/downloads\n<\/div><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Check Python Installation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">On macOS or Linux:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">python3 --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">On Windows:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">py --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected version:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">Python<\/span> 3<span class=\"hljs-selector-class\">.11<\/span><span class=\"hljs-selector-class\">.x<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Or newer.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Check Whether pre-commit Is Already Installed<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If installed, the command returns a version such as:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">pre-commit<\/span> 4<span class=\"hljs-selector-class\">.7<\/span><span class=\"hljs-selector-class\">.0<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Otherwise, follow the installation instructions below.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">4. How to Install pre-commit on macOS<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">macOS users can install pre-commit using Homebrew, pipx, or Python pip.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For most Mac users, Homebrew is the recommended option.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Method 1: Install pre-commit Using Homebrew (Recommended)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Open Terminal<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Open Terminal from:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Applications \u2192 Utilities \u2192 Terminal<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Check macOS Version<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">sw_vers<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Check processor architecture:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">uname -m<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Apple Silicon:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">arm64<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Intel Mac:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">x86_64<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Homebrew supports compatible pre-commit installations on both architectures.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Check Homebrew<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">brew --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If Homebrew is not installed, use its official installation instructions at:<\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/brew.sh\n<\/div><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The official installer command is:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">\/bin\/bash -c <span class=\"hljs-string\">\"$(curl -fsSL https:\/\/raw.githubusercontent.com\/Homebrew\/install\/HEAD\/install.sh)\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Review the script and follow the instructions displayed by the installer.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Update Homebrew<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">brew update<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Step 5: Install pre-commit<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">brew install pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Homebrew installs pre-commit and its required runtime dependencies.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 6: Verify Installation<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected output format:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">pre-commit<\/span> 4<span class=\"hljs-selector-class\">.7<\/span><span class=\"hljs-selector-class\">.0<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The actual version depends on the version available through Homebrew.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 7: Locate the Executable<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">which pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Or:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">command -v pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Typical Apple Silicon Homebrew location:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">\/opt\/homebrew\/bin\/pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Typical Intel Homebrew location:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">\/usr\/local\/bin\/pre-commit<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Step 8: Display Available Commands<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit --help<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>pre-commit is now installed on macOS.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Method 2: Install pre-commit Using pipx<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">pipx is useful when you want to install Python command-line applications into isolated environments.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Install pipx<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">brew install pipx<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Step 2: Configure pipx PATH<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx ensurepath<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Open a new terminal if required.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Install pre-commit<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx install pre-commit<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Step 4: Verify<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Using pipx keeps the pre-commit application separate from your project&#8217;s Python dependencies.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Method 3: Install pre-commit Using pip<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For a Python virtual environment:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">python3<\/span> <span class=\"hljs-selector-tag\">-m<\/span> <span class=\"hljs-selector-tag\">venv<\/span> <span class=\"hljs-selector-class\">.venv<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Activate it:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">source .venv\/bin\/activate<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Install pre-commit:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">python -m pip install pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Verify:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Recommendation:<\/strong> Use Homebrew or pipx for a general workstation installation. Use a project virtual environment when you intentionally manage pre-commit as a project dependency.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">5. How to Install pre-commit on Windows 10\/11<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Windows users can install pre-commit using Python and pipx.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This method works with PowerShell, Windows Terminal, and compatible Git development environments.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Open PowerShell<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Open Windows PowerShell or PowerShell 7.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Check Python<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">py --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Verify Python 3.11 or newer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If Python is missing, download it from:<\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/www.python.org\/downloads\/windows\n<\/div><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">When installing, enable the option to add Python to PATH if offered.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Open a new PowerShell window after installation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Verify pip<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">py -m pip --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If pip is missing:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">py -m ensurepip --upgrade<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 3: Install pipx<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">py -m pip install --user pipx<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Configure its executable path:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">py -m pipx ensurepath<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Close and reopen PowerShell.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Verify:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx --version<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 4: Install pre-commit<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx install pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">pipx creates an isolated Python environment for pre-commit and exposes its executable to your user account.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Verify Installation<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Display help:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit --help<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 6: Locate the Executable<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">Get-Command pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Or:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">where<\/span><span class=\"hljs-selector-class\">.exe<\/span> <span class=\"hljs-selector-tag\">pre-commit<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This helps confirm which installation Windows is using.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>pre-commit is now installed on Windows.<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Alternative: Install Through a Python Virtual Environment<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If you prefer a project-specific setup:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">py<\/span> <span class=\"hljs-selector-tag\">-m<\/span> <span class=\"hljs-selector-tag\">venv<\/span> <span class=\"hljs-selector-class\">.venv<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Activate the environment:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">.\\<span class=\"hljs-selector-class\">.venv<\/span>\\<span class=\"hljs-selector-tag\">Scripts<\/span>\\<span class=\"hljs-selector-tag\">Activate<\/span><span class=\"hljs-selector-class\">.ps1<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Install:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">python -m pip install pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Verify:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If PowerShell blocks activation scripts because of an execution policy, you can invoke the environment&#8217;s Python directly:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">.\\<span class=\"hljs-selector-class\">.venv<\/span>\\<span class=\"hljs-selector-tag\">Scripts<\/span>\\<span class=\"hljs-selector-tag\">python<\/span><span class=\"hljs-selector-class\">.exe<\/span> <span class=\"hljs-selector-tag\">-m<\/span> <span class=\"hljs-selector-tag\">pip<\/span> <span class=\"hljs-selector-tag\">install<\/span> <span class=\"hljs-selector-tag\">pre-commit<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">And verify:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">.\\<span class=\"hljs-selector-class\">.venv<\/span>\\<span class=\"hljs-selector-tag\">Scripts<\/span>\\<span class=\"hljs-selector-tag\">pre-commit<\/span><span class=\"hljs-selector-class\">.exe<\/span> <span class=\"hljs-selector-tag\">--version<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This avoids modifying PowerShell&#8217;s execution policy.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Note:<\/strong> When Git invokes installed hooks, it must still be able to find the pre-commit executable. A user-wide pipx installation is often more convenient for Git hooks used across multiple projects.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">6. How to Install pre-commit on Ubuntu and Debian<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">For Ubuntu and Debian, pipx is a good installation choice because it avoids interfering with system-managed Python packages.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Check Linux Distribution<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">cat \/etc\/os-release<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Check Python:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">python3 --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The current pre-commit version requires Python 3.11 or newer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If your distribution&#8217;s default Python is older, install a supported Python release using your distribution&#8217;s approved repositories before continuing.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Update Package Metadata<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">sudo apt update<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 3: Install Dependencies<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">sudo apt install -y \\\n  git \\\n  python3 \\\n  python3-pip \\\n  python3-venv \\\n  pipx<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 4: Configure pipx<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx ensurepath<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Start a new shell if necessary.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Install pre-commit<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx install pre-commit<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 6: Verify Installation<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Check executable location:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">command -v pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Display help:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit --help<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The installation is complete.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Alternative: Install pre-commit with APT<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Some Debian-based distributions provide a pre-commit package through their repositories:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">sudo apt install pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">However, the distribution package may be older than the current upstream release.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Check:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">apt-cache policy pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">For the current upstream release, pipx is generally preferable.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Alternative: Install Using pip in a Virtual Environment<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create an isolated environment:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">python3 -m venv ~<span class=\"hljs-regexp\">\/.venvs\/<\/span>pre-commit<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Install:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">~<span class=\"hljs-regexp\">\/.venvs\/<\/span>pre-commit\/bin\/python -m pip install pre-commit<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Verify:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">~<span class=\"hljs-regexp\">\/.venvs\/<\/span>pre-commit\/bin\/pre-commit --version<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">To use this executable globally, you can create a symbolic link in a user-local bin directory:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">mkdir -p ~<span class=\"hljs-regexp\">\/.local\/<\/span>bin<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">ln -s ~<span class=\"hljs-regexp\">\/.venvs\/<\/span>pre-commit\/bin\/pre-commit ~<span class=\"hljs-regexp\">\/.local\/<\/span>bin\/pre-commit<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Ensure <code>~\/.local\/bin<\/code> is included in your PATH.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This approach also avoids modifying system Python packages.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">7. How to Install pre-commit on Fedora, RHEL, CentOS, and Rocky Linux<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">On Fedora, pipx can generally be installed using DNF.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For RHEL and compatible distributions where pipx is unavailable in the enabled repositories, a Python virtual environment is a useful alternative.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Method 1: Fedora Installation Using pipx<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Install Dependencies<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">sudo dnf install -y \\\n  git \\\n  python3 \\\n  python3-pip \\\n  pipx<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Step 2: Configure pipx<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx ensurepath<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Open a new terminal.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Install pre-commit<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx install pre-commit<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Step 4: Verify Installation<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit --version<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Method 2: RHEL\/CentOS Installation Using a Virtual Environment<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Install Git and a Compatible Python Runtime<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For systems with appropriate package repositories enabled:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">sudo dnf install -y git python3 python3-pip<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Check:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">python3 --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If the default Python is older than 3.11, install a supported newer version and use that interpreter for the following commands.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Create a Virtual Environment<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">python3 -m venv ~<span class=\"hljs-regexp\">\/.venvs\/<\/span>pre-commit<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Step 3: Install pre-commit<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">~<span class=\"hljs-regexp\">\/.venvs\/<\/span>pre-commit\/bin\/python -m pip install pre-commit<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Step 4: Configure a Command Path<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">mkdir -p ~<span class=\"hljs-regexp\">\/.local\/<\/span>bin<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">ln -s ~<span class=\"hljs-regexp\">\/.venvs\/<\/span>pre-commit\/bin\/pre-commit ~<span class=\"hljs-regexp\">\/.local\/<\/span>bin\/pre-commit<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Add it to Bash&#8217;s PATH if required:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">'export PATH=\"$HOME\/.local\/bin:$PATH\"'<\/span> &gt;&gt; ~\/.bashrc<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Reload:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">source ~\/.bashrc<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Step 5: Verify Installation<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit --version<\/code><\/span><\/pre>\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit --help<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Important:<\/strong> Available Python versions and package names vary across RHEL, CentOS Stream, Rocky Linux, and other RPM-based distributions. Do not replace the system Python interpreter merely to install pre-commit.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">8. Configure pre-commit in a Git Repository<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Installing the pre-commit application is only the first part of the setup.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You must also configure the hooks for each Git repository where you want them to run.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The following steps are the same on macOS, Windows, and Linux.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Navigate to Your Git Repository<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For an existing repository:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">cd \/path\/to\/your\/project<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">On Windows PowerShell, an example is:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">cd C:\\Projects\\my-app<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If you want to create a new demonstration repository:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">mkdir pre-commit-demo\ncd pre-commit-demo\ngit init<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Verify that you are inside a Git repository:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">git status<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If Git displays repository status information, continue.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Create the pre-commit Configuration File<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">pre-commit reads its configuration from:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.pre-commit-config<\/span><span class=\"hljs-selector-class\">.yaml<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The file must be placed in the root of your Git repository.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can create a starter configuration using:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit sample-config<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">To save the generated configuration directly on macOS or Linux:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">pre-commit<\/span> <span class=\"hljs-selector-tag\">sample-config<\/span> &gt; <span class=\"hljs-selector-class\">.pre-commit-config<\/span><span class=\"hljs-selector-class\">.yaml<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">On Windows, you can create or edit the file using VS Code:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">code<\/span> <span class=\"hljs-selector-class\">.pre-commit-config<\/span><span class=\"hljs-selector-class\">.yaml<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Alternatively:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">notepad<\/span> <span class=\"hljs-selector-class\">.pre-commit-config<\/span><span class=\"hljs-selector-class\">.yaml<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If the file does not exist, create it when prompted.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Add a Practical Configuration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For a typical project, use the following configuration:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-28\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\"># .pre-commit-config.yaml<\/span>\n\nminimum_pre_commit_version: <span class=\"hljs-string\">\"4.0.0\"<\/span>\n\nrepos:\n  - repo: https:<span class=\"hljs-comment\">\/\/github.com\/pre-commit\/pre-commit-hooks<\/span>\n    rev: v6<span class=\"hljs-number\">.0<\/span><span class=\"hljs-number\">.0<\/span>\n    hooks:\n      - id: trailing-whitespace\n\n      - id: end-of-file-fixer\n\n      - id: check-yaml\n\n      - id: check-json\n\n      - id: check-toml\n\n      - id: check-merge-conflict\n\n      - id: check-<span class=\"hljs-keyword\">case<\/span>-conflict\n\n      - id: detect-<span class=\"hljs-keyword\">private<\/span>-key\n\n      - id: check-added-large-files\n        args: &#91;--maxkb=<span class=\"hljs-number\">1024<\/span>]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-28\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This is a language-neutral configuration suitable for many software projects.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Understanding the Configuration<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>Setting<\/th><th>Purpose<\/th><\/tr><tr><td><code>minimum_pre_commit_version<\/code><\/td><td>Enforces a minimum supported framework version<\/td><\/tr><tr><td><code>repos<\/code><\/td><td>Lists hook repositories<\/td><\/tr><tr><td><code>repo<\/code><\/td><td>Repository URL containing hooks<\/td><\/tr><tr><td><code>rev<\/code><\/td><td>Version, tag, or commit to use<\/td><\/tr><tr><td><code>hooks<\/code><\/td><td>Hooks enabled from that repository<\/td><\/tr><tr><td><code>id<\/code><\/td><td>Identifier of a particular hook<\/td><\/tr><tr><td><code>args<\/code><\/td><td>Additional command-line arguments<\/td><\/tr><tr><td><code>files<\/code><\/td><td>Regex matching files the hook should process<\/td><\/tr><tr><td><code>exclude<\/code><\/td><td>Regex excluding files from processing<\/td><\/tr><tr><td><code>stages<\/code><\/td><td>Git hook stages on which a hook should run<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">What Do These Hooks Check?<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>Hook<\/th><th>Function<\/th><\/tr><tr><td><code>trailing-whitespace<\/code><\/td><td>Removes trailing whitespace<\/td><\/tr><tr><td><code>end-of-file-fixer<\/code><\/td><td>Ensures a consistent final newline<\/td><\/tr><tr><td><code>check-yaml<\/code><\/td><td>Checks YAML syntax<\/td><\/tr><tr><td><code>check-json<\/code><\/td><td>Checks JSON syntax<\/td><\/tr><tr><td><code>check-toml<\/code><\/td><td>Checks TOML syntax<\/td><\/tr><tr><td><code>check-merge-conflict<\/code><\/td><td>Detects common unresolved merge conflict markers<\/td><\/tr><tr><td><code>check-case-conflict<\/code><\/td><td>Detects filenames that conflict on case-insensitive filesystems<\/td><\/tr><tr><td><code>detect-private-key<\/code><\/td><td>Detects certain private-key patterns<\/td><\/tr><tr><td><code>check-added-large-files<\/code><\/td><td>Prevents staged additions exceeding the configured size limit<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In this example, <code>--maxkb=1024<\/code> sets the added-file limit to 1,024 KB.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Security note:<\/strong> <code>detect-private-key<\/code> is not a comprehensive secret scanner. Consider a dedicated secret-scanning tool for broader credential detection.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Validate the Configuration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit validate-config<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If the command exits successfully without errors, the configuration is syntactically valid according to pre-commit&#8217;s configuration schema.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Install the Git Hook<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Execute:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit install<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Example output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit installed at .git\/hooks\/pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This installs the Git hook launcher for the current repository.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">From this point onward, a normal <code>git commit<\/code> triggers configured pre-commit-stage hooks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Important:<\/strong> This step is repository-specific. Every developer must install the hook in their local clone, unless their development environment already provides equivalent setup automation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6: Download and Prepare Hook Environments<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You can initialize hook environments before your first commit:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit install-hooks<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This downloads and prepares the required hook environments.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The initial run may take longer because hook dependencies must be installed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Subsequent runs can reuse cached environments.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 7: Run Hooks Against All Files<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Execute:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit run --all-files<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This checks applicable Git-tracked files in the repository.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Example output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-29\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">Trim<\/span> <span class=\"hljs-selector-tag\">Trailing<\/span> <span class=\"hljs-selector-tag\">Whitespace<\/span>.......................<span class=\"hljs-selector-class\">.Passed<\/span>\n<span class=\"hljs-selector-tag\">Fix<\/span> <span class=\"hljs-selector-tag\">End<\/span> <span class=\"hljs-selector-tag\">of<\/span> <span class=\"hljs-selector-tag\">Files<\/span>...............................<span class=\"hljs-selector-class\">.Passed<\/span>\n<span class=\"hljs-selector-tag\">Check<\/span> <span class=\"hljs-selector-tag\">Yaml<\/span>.....................................<span class=\"hljs-selector-class\">.Passed<\/span>\n<span class=\"hljs-selector-tag\">Check<\/span> <span class=\"hljs-selector-tag\">JSON<\/span>.....................................<span class=\"hljs-selector-class\">.Passed<\/span>\n<span class=\"hljs-selector-tag\">Check<\/span> <span class=\"hljs-selector-tag\">Toml<\/span>.....................................<span class=\"hljs-selector-class\">.Passed<\/span>\n<span class=\"hljs-selector-tag\">Check<\/span> <span class=\"hljs-selector-tag\">for<\/span> <span class=\"hljs-selector-tag\">merge<\/span> <span class=\"hljs-selector-tag\">conflicts<\/span>......................<span class=\"hljs-selector-class\">.Passed<\/span>\n<span class=\"hljs-selector-tag\">Check<\/span> <span class=\"hljs-selector-tag\">for<\/span> <span class=\"hljs-selector-tag\">case<\/span> <span class=\"hljs-selector-tag\">conflicts<\/span>........................<span class=\"hljs-selector-class\">.Passed<\/span>\n<span class=\"hljs-selector-tag\">Detect<\/span> <span class=\"hljs-selector-tag\">Private<\/span> <span class=\"hljs-selector-tag\">Key<\/span>............................<span class=\"hljs-selector-class\">.Passed<\/span>\n<span class=\"hljs-selector-tag\">Check<\/span> <span class=\"hljs-selector-tag\">for<\/span> <span class=\"hljs-selector-tag\">added<\/span> <span class=\"hljs-selector-tag\">large<\/span> <span class=\"hljs-selector-tag\">files<\/span>....................<span class=\"hljs-selector-class\">.Passed<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-29\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The exact output depends on the files in your repository.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A hook may report <code>Skipped<\/code> when no files match its conditions.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">9. Test pre-commit with a Real Git Commit<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Now let&#8217;s confirm that pre-commit runs automatically.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Create a Sample File<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">On macOS\/Linux:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-30\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">printf <span class=\"hljs-string\">'name: demo\\n'<\/span> &gt; example.yaml<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-30\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">On Windows PowerShell:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-31\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-built_in\">Set<\/span>-Content -Path example.yaml -Value <span class=\"hljs-string\">\"name: demo\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-31\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 2: Stage the Files<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-32\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">git<\/span> <span class=\"hljs-selector-tag\">add<\/span> <span class=\"hljs-selector-class\">.pre-commit-config<\/span><span class=\"hljs-selector-class\">.yaml<\/span> <span class=\"hljs-selector-tag\">example<\/span><span class=\"hljs-selector-class\">.yaml<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-32\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 3: Create a Commit<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-33\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">git commit -m <span class=\"hljs-string\">\"Add pre-commit configuration\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-33\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Before creating the commit, Git invokes the installed pre-commit hook.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If all checks pass, Git continues creating the commit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If a check fails, the commit is normally blocked.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If the hook automatically fixes a file, review and stage the updated file before retrying.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">git status<\/code><\/span><\/pre>\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">git diff<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Then:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-34\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">git<\/span> <span class=\"hljs-selector-tag\">add<\/span> <span class=\"hljs-selector-tag\">example<\/span><span class=\"hljs-selector-class\">.yaml<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-34\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Retry:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-35\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">git commit -m <span class=\"hljs-string\">\"Add pre-commit configuration\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-35\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If Git reports that your author identity is not configured, follow Git&#8217;s instructions to set <code>user.name<\/code> and <code>user.email<\/code> before retrying.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">10. Essential pre-commit Commands<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The following commands are useful for everyday development.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>Command<\/th><th>Purpose<\/th><\/tr><tr><td><code>pre-commit --version<\/code><\/td><td>Display installed version<\/td><\/tr><tr><td><code>pre-commit --help<\/code><\/td><td>Show available commands<\/td><\/tr><tr><td><code>pre-commit sample-config<\/code><\/td><td>Generate a sample configuration<\/td><\/tr><tr><td><code>pre-commit validate-config<\/code><\/td><td>Validate configuration syntax<\/td><\/tr><tr><td><code>pre-commit install<\/code><\/td><td>Install Git hook launcher<\/td><\/tr><tr><td><code>pre-commit install-hooks<\/code><\/td><td>Prepare hook environments<\/td><\/tr><tr><td><code>pre-commit run<\/code><\/td><td>Run applicable hooks on staged files<\/td><\/tr><tr><td><code>pre-commit run --all-files<\/code><\/td><td>Run applicable hooks on all tracked files<\/td><\/tr><tr><td><code>pre-commit run check-yaml --all-files<\/code><\/td><td>Run one specific hook<\/td><\/tr><tr><td><code>pre-commit run --files example.yaml<\/code><\/td><td>Run applicable hooks on one file<\/td><\/tr><tr><td><code>pre-commit autoupdate<\/code><\/td><td>Update hook repository revisions<\/td><\/tr><tr><td><code>pre-commit clean<\/code><\/td><td>Remove cached hook environments<\/td><\/tr><tr><td><code>pre-commit gc<\/code><\/td><td>Remove unused cached repositories<\/td><\/tr><tr><td><code>pre-commit uninstall<\/code><\/td><td>Remove installed Git hook launcher<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Run a Specific Hook<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit run trailing-whitespace --all-files<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Validate Only YAML Files<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit run check-yaml --all-files<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Run Against Specific Files<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-36\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">pre-commit<\/span> <span class=\"hljs-selector-tag\">run<\/span> <span class=\"hljs-selector-tag\">--files<\/span> <span class=\"hljs-selector-tag\">README<\/span><span class=\"hljs-selector-class\">.md<\/span> <span class=\"hljs-selector-tag\">example<\/span><span class=\"hljs-selector-class\">.yaml<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-36\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Display More Information on Failed Hooks<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit run --all-files --verbose<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Show Diffs When Hooks Modify Files<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit run --all-files --show-diff-on-failure<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This is particularly useful in CI\/CD pipelines.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">11. Configure pre-commit for Python Projects<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Python projects can use pre-commit to execute formatters and linters automatically.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ruff provides Python linting and formatting functionality.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To configure Ruff, add the following repository to your existing <code>.pre-commit-config.yaml<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> <code> - repo: https:\/\/github.com\/astral-sh\/ruff-pre-commit\n    rev: v0.16.10\n    hooks:\n      - id: ruff-check\n        args: [--fix]\n\n      - id: ruff-format<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The version above is an example of a published Ruff hook release. Keep its pinned version aligned with the Ruff configuration and compatibility requirements of your project.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What Happens?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When Python files are committed:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>Ruff checks the Python code.<\/li>\n\n\n\n<li>Ruff applies supported automatic lint fixes.<\/li>\n\n\n\n<li>Ruff formats the code.<\/li>\n\n\n\n<li>pre-commit reports failures or modified files.<\/li>\n\n\n\n<li>The developer reviews and stages any changes.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Run manually:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit run ruff-check --all-files<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Format all applicable tracked Python files:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit run ruff-format --all-files<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Recommendation:<\/strong> Keep the Ruff linting hook before the formatting hook when enabling <code>--fix<\/code>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">12. Configure pre-commit for Terraform Projects<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">For Infrastructure-as-Code projects, pre-commit can help maintain consistent Terraform formatting and perform additional checks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A popular hook collection is:<\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/github.com\/antonbabenko\/pre-commit-terraform\n<\/div><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Add the following to your configuration:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> <code> - repo: https:\/\/github.com\/antonbabenko\/pre-commit-terraform\n    rev: v1.108.1\n    hooks:\n      - id: terraform_fmt<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This example enables Terraform formatting.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Run Terraform Formatting<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit run terraform_fmt --all-files<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Add Terraform Validation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If your project needs additional Terraform validation, you can add:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> <code>     - id: terraform_validate<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">However, Terraform validation may require initialized working directories, provider plugins, module downloads, and suitable backend configuration.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Terraform and other required supporting tools must be available for these hooks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For Windows users, WSL is often a practical environment for shell-oriented Terraform pre-commit hook integrations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Best practice:<\/strong> Run fast formatting checks before commits, and place more expensive Terraform validation, linting, and security checks in CI\/CD when appropriate.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">13. Configure Different Git Hook Stages<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">pre-commit can manage more than the standard <code>pre-commit<\/code> Git hook.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It supports stages such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>pre-commit<\/code><\/li>\n\n\n\n<li><code>pre-push<\/code><\/li>\n\n\n\n<li><code>commit-msg<\/code><\/li>\n\n\n\n<li><code>pre-merge-commit<\/code><\/li>\n\n\n\n<li><code>post-checkout<\/code><\/li>\n\n\n\n<li><code>post-merge<\/code><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Example: Install Both pre-commit and pre-push Hooks<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit install \\\n  --hook-type pre-commit \\\n  --hook-type pre-push<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">For Windows PowerShell, use one line:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit install --hook-type pre-commit --hook-type pre-push<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">You can specify hook stages in your configuration.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-37\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">default_install_hook_types:\n  - pre-commit\n  - pre-push\n\n<span class=\"hljs-attr\">repos<\/span>:\n  - repo: https:<span class=\"hljs-comment\">\/\/github.com\/pre-commit\/pre-commit-hooks<\/span>\n    rev: v6<span class=\"hljs-number\">.0<\/span><span class=\"hljs-number\">.0<\/span>\n    <span class=\"hljs-attr\">hooks<\/span>:\n      - id: trailing-whitespace\n        <span class=\"hljs-attr\">stages<\/span>: &#91;pre-commit]\n\n      - id: check-yaml\n        <span class=\"hljs-attr\">stages<\/span>: &#91;pre-commit, pre-push]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-37\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">With this configuration:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Trailing whitespace checks run before commits.<\/li>\n\n\n\n<li>YAML validation runs before commits and pushes.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A <code>git push<\/code> will trigger the installed pre-push hook.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Remember that a hook&#8217;s configured stages and the Git hook launchers installed in the repository must both be correct for it to run automatically.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">14. Exclude Files and Directories from pre-commit<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Some files should not be formatted or checked automatically.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Common examples include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Generated files.<\/li>\n\n\n\n<li>Build outputs.<\/li>\n\n\n\n<li>Dependency directories.<\/li>\n\n\n\n<li>Large vendor directories.<\/li>\n\n\n\n<li>Compiled artifacts.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">You can exclude paths using regular expressions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Example:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">exclude: |\n  (?x)^(\n    node_modules\/|\n    dist\/|\n    build\/|\n    vendor\/|\n    coverage\/|\n    \\.venv\/|\n    \\.terraform\/\n  )<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Add this at the top level of <code>.pre-commit-config.yaml<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For individual hooks:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-38\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">repos:\n  - repo: https:<span class=\"hljs-comment\">\/\/github.com\/pre-commit\/pre-commit-hooks<\/span>\n    rev: v6<span class=\"hljs-number\">.0<\/span><span class=\"hljs-number\">.0<\/span>\n    <span class=\"hljs-attr\">hooks<\/span>:\n      - id: trailing-whitespace\n        <span class=\"hljs-attr\">exclude<\/span>: ^generated\/<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-38\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This excludes files under <code>generated\/<\/code> from that specific hook.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Important:<\/strong> Exclusions use regular expressions and apply to the files pre-commit considers. They are not identical to <code>.gitignore<\/code> patterns.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">15. Run pre-commit Automatically in GitHub Actions<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Local Git hooks are useful, but developers can skip them or forget to install them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For consistent team enforcement, run the same checks in CI\/CD.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">GitHub Actions is one option.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Create the Workflow Directory<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">On macOS\/Linux:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">mkdir -p .github\/workflows<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">On Windows PowerShell:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-39\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">New<\/span>-Item -ItemType Directory -Force -Path .github\/workflows<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-39\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Step 2: Create a Workflow File<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">.github\/workflows\/pre-commit.yml<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Add:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-40\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">name: Pre-commit Checks\n\n<span class=\"hljs-attr\">on<\/span>:\n  push:\n  pull_request:\n\npermissions:\n  contents: read\n\n<span class=\"hljs-attr\">jobs<\/span>:\n  pre-commit:\n    runs-on: ubuntu-latest\n\n    <span class=\"hljs-attr\">steps<\/span>:\n      - name: Checkout repository\n        <span class=\"hljs-attr\">uses<\/span>: actions\/checkout@v7\n\n      - name: <span class=\"hljs-built_in\">Set<\/span> up Python\n        <span class=\"hljs-attr\">uses<\/span>: actions\/setup-python@v7\n        <span class=\"hljs-attr\">with<\/span>:\n          python-version: <span class=\"hljs-string\">\"3.13\"<\/span>\n\n      - name: Install pre-commit\n        <span class=\"hljs-attr\">run<\/span>: python -m pip install pre-commit==<span class=\"hljs-number\">4.7<\/span><span class=\"hljs-number\">.0<\/span>\n\n      - name: Validate configuration\n        <span class=\"hljs-attr\">run<\/span>: pre-commit validate-config\n\n      - name: Run all hooks\n        <span class=\"hljs-attr\">run<\/span>: pre-commit run --all-files --show-diff-on-failure<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-40\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This workflow:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>Checks out the repository.<\/li>\n\n\n\n<li>Configures Python.<\/li>\n\n\n\n<li>Installs the specified pre-commit version.<\/li>\n\n\n\n<li>Validates the configuration.<\/li>\n\n\n\n<li>Executes configured hooks against applicable tracked files.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">If a hook fails or modifies a file, the GitHub Actions job fails, allowing the developer to review the issue.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For stricter software supply-chain controls, pin GitHub Actions to reviewed commit SHAs and restrict the permissions available to workflow jobs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Optional: Test Across Multiple Operating Systems<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To verify cross-platform behavior, use:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">strategy:\n  matrix:\n    os:\n      - ubuntu-latest\n      - windows-latest\n      - macos-latest\n\nruns-on: ${{ matrix.os }}<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Add this matrix to the job and use the matrix variable instead of a single <code>runs-on<\/code> value.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Running checks in CI\/CD helps ensure that contributors receive consistent results even when local hooks are missing.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">16. How to Update pre-commit<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">There are two different kinds of updates:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>Updating the pre-commit framework.<\/li>\n\n\n\n<li>Updating hook versions in <code>.pre-commit-config.yaml<\/code>.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">These are separate operations.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Update pre-commit on macOS<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Homebrew:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">brew update\nbrew upgrade pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">pipx:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx upgrade pre-commit<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Update pre-commit on Windows<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For a pipx installation:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx upgrade pre-commit<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Update pre-commit on Linux<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For a pipx installation:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx upgrade pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">For a virtual-environment installation:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-41\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">~<span class=\"hljs-regexp\">\/.venvs\/<\/span>pre-commit\/bin\/python -m pip install --upgrade pre-commit<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-41\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Update Configured Hook Versions<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit autoupdate<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This updates the hook repository revisions in <code>.pre-commit-config.yaml<\/code> to newer available versions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After updating, run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit validate-config<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Then:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit run --all-files<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Review the resulting changes before committing them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Production recommendation:<\/strong> Avoid automatically accepting every hook upgrade. Review release notes and compatibility changes before rolling updated hooks out to a team.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">17. Troubleshooting Common pre-commit Errors<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The following table summarizes common installation and configuration problems.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>Error or symptom<\/th><th>Possible cause<\/th><th>Recommended solution<\/th><\/tr><tr><td><code>pre-commit: command not found<\/code><\/td><td>Executable missing from PATH<\/td><td>Verify installation and PATH<\/td><\/tr><tr><td><code>pre-commit is not recognized<\/code><\/td><td>Windows PATH not refreshed<\/td><td>Restart PowerShell and check installation<\/td><\/tr><tr><td><code>No .pre-commit-config.yaml file was found<\/code><\/td><td>Configuration file missing<\/td><td>Create the file in the repository root<\/td><\/tr><tr><td><code>InvalidConfigError<\/code><\/td><td>Incorrect YAML or configuration format<\/td><td>Run <code>pre-commit validate-config<\/code><\/td><\/tr><tr><td><code>git failed<\/code><\/td><td>Git unavailable or repository problem<\/td><td>Verify Git and repository status<\/td><\/tr><tr><td><code>externally-managed-environment<\/code><\/td><td>System Python managed by OS<\/td><td>Use pipx or a virtual environment<\/td><\/tr><tr><td><code>Permission denied<\/code><\/td><td>Installation or execution permissions<\/td><td>Check executable permissions<\/td><\/tr><tr><td><code>Failed to create environment<\/code><\/td><td>Python\/runtime\/dependency issue<\/td><td>Check required runtime and hook dependencies<\/td><\/tr><tr><td><code>Files were modified by this hook<\/code><\/td><td>Formatter changed files<\/td><td>Review and stage changes again<\/td><\/tr><tr><td><code>An unexpected error has occurred<\/code><\/td><td>Hook installation or execution failure<\/td><td>Inspect detailed output and pre-commit log<\/td><\/tr><tr><td>Hook never runs on commit<\/td><td>Git launcher not installed or custom hooks path<\/td><td>Reinstall and inspect Git hook configuration<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting 1: pre-commit Command Not Found<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">On macOS\/Linux:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">command -v pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Check:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-42\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"$PATH\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-42\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">For a pipx installation:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-43\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">pipx <span class=\"hljs-keyword\">list<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-43\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx ensurepath<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Open a new terminal and retry.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting 2: pre-commit Not Recognized on Windows<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">Get-Command pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Inspect pipx installations:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-44\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">pipx <span class=\"hljs-keyword\">list<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-44\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Refresh PATH configuration:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">py -m pipx ensurepath<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Open a new PowerShell window.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting 3: Invalid Configuration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-45\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">InvalidConfigError:\n==&gt; File .pre-commit-config.yaml<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-45\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Check the YAML syntax and configuration schema.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit validate-config<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Common mistakes include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Incorrect indentation.<\/li>\n\n\n\n<li>Missing <code>repos<\/code> entries.<\/li>\n\n\n\n<li>Invalid hook IDs.<\/li>\n\n\n\n<li>Invalid stage names.<\/li>\n\n\n\n<li>Incorrect YAML list formatting.<\/li>\n\n\n\n<li>Unsupported configuration properties.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting 4: Python Version Not Supported<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Verify:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">python3 --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Or on Windows:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">py --version<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">pre-commit 4.7.0 requires Python 3.11 or newer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Install or select a compatible Python runtime, then reinstall pre-commit using that runtime.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Hook environments can have additional language-version requirements of their own.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting 5: Files Were Modified by This Hook<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Example output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-46\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">Trim Trailing Whitespace................Failed\n- hook id: trailing-whitespace\n- exit code: <span class=\"hljs-number\">1<\/span>\n- files were modified by <span class=\"hljs-keyword\">this<\/span> hook<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-46\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This does not necessarily mean the tool is broken.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The hook may have successfully fixed a formatting problem and intentionally stopped the commit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Review the changes:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">git diff<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Stage the modified files:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">git add .<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Run checks again:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit run --all-files<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Then retry the commit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When working in an existing repository, stage only the files you intend to commit instead of using <code>git add .<\/code> indiscriminately.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting 6: pre-commit Does Not Execute During Git Commit<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check the Git hooks path:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-47\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">git config --<span class=\"hljs-keyword\">get<\/span> core.hooksPath<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-47\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">A custom hooks directory may cause Git to ignore the normal <code>.git\/hooks<\/code> directory.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Reinstall the launcher:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit install<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If the repository uses a custom <code>core.hooksPath<\/code>, integrate pre-commit with that existing hook-management approach rather than overwriting another tool&#8217;s configuration without review.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting 7: Clear Broken Hook Environments<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If a cached hook environment appears corrupted, run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit clean<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Then:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit install-hooks<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Finally:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit run --all-files<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This forces the required hook environments to be rebuilt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Do not treat cache clearing as a fix for invalid credentials, unavailable dependencies, or broken configuration files.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">18. How to Temporarily Skip pre-commit Hooks<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Occasionally, a developer may need to skip a particular hook for a legitimate reason.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">pre-commit supports the <code>SKIP<\/code> environment variable.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">macOS\/Linux<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-48\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">SKIP=check-yaml git commit -m <span class=\"hljs-string\">\"Temporary commit\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-48\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This skips only the configured hook with the specified ID.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Windows PowerShell<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-49\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$env:SKIP = <span class=\"hljs-string\">\"check-yaml\"<\/span>\n\ngit commit -m <span class=\"hljs-string\">\"Temporary commit\"<\/span>\n\nRemove-Item Env:\\SKIP<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-49\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Skip All Git Commit Verification Hooks<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Git also supports:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-50\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">git commit --no-verify -m <span class=\"hljs-string\">\"Temporary commit\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-50\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">However, this bypasses applicable Git commit verification hooks, not just a single pre-commit check.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Best practice:<\/strong> Avoid bypassing checks except for clearly justified situations. CI\/CD should independently enforce the project&#8217;s required checks.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">19. How to Uninstall pre-commit<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">If you want to remove pre-commit from a repository, first remove the Git hook launcher.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Navigate to the repository:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">cd \/path\/to\/your\/project<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Execute:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit uninstall<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">This removes the installed pre-commit Git hook launcher.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can then remove the application using the package manager that installed it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">macOS \u2014 Homebrew<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">brew uninstall pre-commit<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">macOS\/Windows\/Linux \u2014 pipx<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx uninstall pre-commit<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Ubuntu\/Debian \u2014 APT<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">sudo apt remove pre-commit<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Project Virtual Environment<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If pre-commit is installed in an activated virtual environment:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">python -m pip uninstall pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Removing the application does not automatically remove every repository configuration file.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you no longer want the project configuration, remove <code>.pre-commit-config.yaml<\/code> separately and update the repository as appropriate.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">20. pre-commit Installation Command Cheat Sheet<\/h1>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>Operating system<\/th><th>Recommended installation<\/th><\/tr><tr><td>macOS Intel<\/td><td><code>brew install pre-commit<\/code><\/td><\/tr><tr><td>macOS Apple Silicon<\/td><td><code>brew install pre-commit<\/code><\/td><\/tr><tr><td>Windows 10\/11<\/td><td><code>pipx install pre-commit<\/code><\/td><\/tr><tr><td>Ubuntu<\/td><td><code>pipx install pre-commit<\/code><\/td><\/tr><tr><td>Debian<\/td><td><code>pipx install pre-commit<\/code><\/td><\/tr><tr><td>Fedora<\/td><td><code>pipx install pre-commit<\/code><\/td><\/tr><tr><td>RHEL\/CentOS<\/td><td>Install using pipx or an isolated Python virtual environment<\/td><\/tr><tr><td>macOS\/Linux with pipx<\/td><td><code>pipx install pre-commit<\/code><\/td><\/tr><tr><td>Python virtual environment<\/td><td><code>python -m pip install pre-commit<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Essential Configuration Commands<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-51\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\"># Check version<\/span>\npre-commit --version\n\n<span class=\"hljs-comment\"># Generate sample configuration<\/span>\npre-commit sample-config\n\n<span class=\"hljs-comment\"># Validate configuration<\/span>\npre-commit validate-config\n\n<span class=\"hljs-comment\"># Install Git hook<\/span>\npre-commit install\n\n<span class=\"hljs-comment\"># Install hook environments<\/span>\npre-commit install-hooks\n\n<span class=\"hljs-comment\"># Run against all tracked files<\/span>\npre-commit run --all-files\n\n<span class=\"hljs-comment\"># Run on staged files<\/span>\npre-commit run\n\n<span class=\"hljs-comment\"># Update hook versions<\/span>\npre-commit autoupdate\n\n<span class=\"hljs-comment\"># Clear cached environments<\/span>\npre-commit clean\n\n<span class=\"hljs-comment\"># Remove installed Git hook<\/span>\npre-commit uninstall<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-51\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">21. Frequently Asked Questions<\/h1>\n\n\n\n<h3 class=\"wp-block-heading\">Q1. Is pre-commit free and open source?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. pre-commit is an open-source framework distributed under the MIT license.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Q2. Is pre-commit only for Python projects?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. Although pre-commit is implemented in Python, it supports hooks for many languages and tools, including JavaScript, Python, Go, Ruby, and others.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Q3. Does pre-commit support Terraform?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. Community hook collections provide Terraform formatting, validation, and other Infrastructure-as-Code checks.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Q4. Does pre-commit work on Windows?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. pre-commit supports Windows and can be installed through Python tooling such as pipx.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Some individual hooks may require WSL or other platform-specific dependencies, so check the requirements of each hook.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Q5. Is pre-commit automatically enabled after installation?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Installing the executable makes the command available, but you must configure it in your repository and run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit install<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Q6. Does pre-commit run automatically when I commit?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes, after the appropriate Git hook launcher is installed in that repository.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Q7. Does pre-commit check every file during each commit?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Normally, pre-commit-stage hooks operate on applicable staged files.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To check all applicable tracked files:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit run --all-files<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Q8. Can pre-commit automatically fix code?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. Many hooks can modify files to correct formatting or other supported issues.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Not every hook supports automatic fixes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Q9. Can pre-commit detect secrets?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">It can run hooks that detect certain secrets or private-key patterns.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For broader protection, integrate a dedicated secret scanner and server-side secret detection.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Q10. Should pre-commit run in CI\/CD?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. Running the same checks in CI\/CD reduces the risk of bypassed or missing local hooks.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Q11. Can I run pre-commit without installing Git hooks?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. With a configuration present, you can run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pre-commit run --all-files<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The Git launcher is required for automatic execution during commits, not for manual execution.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Q12. Does pre-commit replace code review?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. It helps automate repetitive checks but does not replace human review of correctness, architecture, security, or maintainability.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">22. Best Practices for Teams and Production Projects<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">For reliable adoption across development teams, follow these recommendations:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>Keep <code>.pre-commit-config.yaml<\/code> under version control.<\/li>\n\n\n\n<li>Pin hook repositories to reviewed versions or commit references.<\/li>\n\n\n\n<li>Use the same configuration locally and in CI\/CD.<\/li>\n\n\n\n<li>Select fast hooks for the pre-commit stage.<\/li>\n\n\n\n<li>Run expensive tests and scans in CI\/CD or pre-push stages when appropriate.<\/li>\n\n\n\n<li>Use <code>pre-commit run --all-files<\/code> when introducing new hooks to an existing repository.<\/li>\n\n\n\n<li>Review automatic formatting changes before committing.<\/li>\n\n\n\n<li>Avoid excluding large portions of the codebase without a clear reason.<\/li>\n\n\n\n<li>Do not rely on local hooks alone for security enforcement.<\/li>\n\n\n\n<li>Use standard, maintained hook collections rather than unnecessary custom scripts.<\/li>\n\n\n\n<li>Review third-party hooks before executing them because hooks can run code on developer machines and CI runners.<\/li>\n\n\n\n<li>Update hook versions through a controlled review process.<\/li>\n\n\n\n<li>Document any platform-specific requirements for contributors.<\/li>\n\n\n\n<li>Include pre-commit setup instructions in the project README or onboarding documentation.<\/li>\n\n\n\n<li>Keep hook execution fast enough that developers do not routinely bypass it.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">23. Conclusion<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">pre-commit is a practical tool for improving code consistency, reducing avoidable mistakes, and bringing automated quality checks earlier into the development workflow.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It works across macOS, Windows, and Linux and can be used with virtually any Git-based software project.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For most users, installation is straightforward:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>macOS:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">brew install pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Windows:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx install pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><strong>Linux:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">pipx install pre-commit<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Once installed, the essential setup process is:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-52\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\"># Create or configure .pre-commit-config.yaml<\/span>\n\n<span class=\"hljs-comment\"># Validate configuration<\/span>\npre-commit validate-config\n\n<span class=\"hljs-comment\"># Install the Git hook<\/span>\npre-commit install\n\n<span class=\"hljs-comment\"># Prepare hook environments<\/span>\npre-commit install-hooks\n\n<span class=\"hljs-comment\"># Run against all tracked files<\/span>\npre-commit run --all-files<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-52\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">From that point onward, supported hooks automatically execute when the corresponding Git events occur.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">By combining local pre-commit hooks with CI\/CD checks, development teams can catch common issues earlier, maintain consistent coding standards, and spend more time reviewing meaningful code changes rather than repetitive formatting problems.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Official Documentation and References<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>pre-commit Official Website:<\/strong> <a href=\"https:\/\/pre-commit.com\/\">https:\/\/pre-commit.com\/<\/a><\/li>\n\n\n\n<li><strong>pre-commit GitHub Repository:<\/strong> <a href=\"https:\/\/github.com\/pre-commit\/pre-commit\">https:\/\/github.com\/pre-commit\/pre-commit<\/a><\/li>\n\n\n\n<li><strong>pre-commit Releases:<\/strong> <a href=\"https:\/\/github.com\/pre-commit\/pre-commit\/releases\/latest\">https:\/\/github.com\/pre-commit\/pre-commit\/releases\/latest<\/a><\/li>\n\n\n\n<li><strong>Official pre-commit-hooks Collection:<\/strong> <a href=\"https:\/\/github.com\/pre-commit\/pre-commit-hooks\">https:\/\/github.com\/pre-commit\/pre-commit-hooks<\/a><\/li>\n\n\n\n<li><strong>Homebrew pre-commit Package:<\/strong> <a href=\"https:\/\/formulae.brew.sh\/formula\/pre-commit\">https:\/\/formulae.brew.sh\/formula\/pre-commit<\/a><\/li>\n\n\n\n<li><strong>pipx Installation Documentation:<\/strong> <a href=\"https:\/\/pipx.pypa.io\/latest\/how-to\/install-pipx.html\">https:\/\/pipx.pypa.io\/latest\/how-to\/install-pipx.html<\/a><\/li>\n\n\n\n<li><strong>Ruff pre-commit Hooks:<\/strong> <a href=\"https:\/\/github.com\/astral-sh\/ruff-pre-commit\">https:\/\/github.com\/astral-sh\/ruff-pre-commit<\/a><\/li>\n\n\n\n<li><strong>Terraform pre-commit Hooks:<\/strong> <a href=\"https:\/\/github.com\/antonbabenko\/pre-commit-terraform\">https:\/\/github.com\/antonbabenko\/pre-commit-terraform<\/a><\/li>\n\n\n\n<li><strong>Git Documentation:<\/strong> <a href=\"https:\/\/git-scm.com\/docs\/githooks\">https:\/\/git-scm.com\/docs\/githooks<\/a><\/li>\n\n\n\n<li><strong>GitHub Actions Documentation:<\/strong> <a href=\"https:\/\/docs.github.com\/en\/actions\">https:\/\/docs.github.com\/en\/actions<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Last reviewed: October 20, 2026. Package versions, supported Python releases, hook dependencies, and installation methods may change. Always verify the official documentation before rolling out new versions in production environments.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>SEO Title: How to Install and Configure pre-commit on Mac, Windows &amp; Linux (2026) Meta Description: Learn how to install and configure pre-commit Git hooks on macOS,&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[11138],"tags":[],"class_list":["post-79428","post","type-post","status-publish","format-standard","hentry","category-best-tools"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/79428","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=79428"}],"version-history":[{"count":1,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/79428\/revisions"}],"predecessor-version":[{"id":79429,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/79428\/revisions\/79429"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=79428"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=79428"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=79428"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}