Git
Commit Hooks
Programming
Version Control
Software Development

Skip Git commit hooks

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

To skip Git commit hooks, add --no-verify (or -n for short) to your git commit command: git commit --no-verify -m "your message". This bypasses pre-commit and commit-msg hooks. This article covers when skipping hooks is appropriate, how to do it for different Git operations, and how to selectively skip specific hooks without disabling all of them.

What Git Hooks Are and Why They Run

Git hooks are scripts that Git executes at specific points in a workflow. They live in .git/hooks/ and are triggered automatically. Here are the commit-related hooks that --no-verify affects:

HookWhen It RunsWhat It Typically Does
pre-commitBefore the commit message editor opensLinting, formatting, running tests
commit-msgAfter the commit message is enteredValidating commit message format

And here are hooks that --no-verify does not skip:

HookWhen It RunsHow to Skip
prepare-commit-msgBefore the editor opensCannot be skipped with a flag
post-commitAfter the commit is createdCannot be skipped with a flag
pre-pushBefore git push sends datagit push --no-verify
pre-rebaseBefore rebase startsCannot be skipped with a flag

Method 1: The --no-verify Flag

The standard approach for a one-off skip:

bash
1# Full flag
2git commit --no-verify -m "fix: urgent hotfix for production"
3
4# Short flag
5git commit -n -m "fix: urgent hotfix for production"

This skips both pre-commit and commit-msg hooks. The commit goes through regardless of what the hooks would have done.

--no-verify works with other Git commands too

bash
1# Skip pre-push hooks
2git push --no-verify
3
4# Skip pre-commit hook during merge commit
5git merge --no-verify feature-branch
6
7# Skip hooks during cherry-pick
8git cherry-pick --no-verify abc1234
9
10# Skip hooks during revert
11git revert --no-verify abc1234

Method 2: Temporarily Disable a Specific Hook

If you want to disable a hook for a period (not just one commit), make it non-executable:

bash
1# Disable pre-commit hook
2chmod -x .git/hooks/pre-commit
3
4# Do your work...
5git commit -m "wip: work in progress"
6git commit -m "wip: more changes"
7
8# Re-enable
9chmod +x .git/hooks/pre-commit

On Windows (where chmod does not work the same way), rename the hook:

batch
1ren .git\hooks\pre-commit pre-commit.disabled
2
3:: Re-enable
4ren .git\hooks\pre-commit.disabled pre-commit

Method 3: Environment Variables (For Hook-Aware Scripts)

Many modern hook frameworks (Husky, pre-commit, lint-staged) check environment variables:

Husky (v9+)

bash
1# Skip all hooks for one command
2HUSKY=0 git commit -m "wip: skip hooks"
3
4# Persistent (current terminal session)
5export HUSKY=0
6git commit -m "commit 1"
7git commit -m "commit 2"
8unset HUSKY

pre-commit framework (Python)

bash
1# Skip all hooks
2SKIP=all git commit -m "wip: skip hooks"
3
4# Skip specific hooks by ID
5SKIP=flake8,mypy git commit -m "wip: skip linting"
6
7# Skip specific stages
8PRE_COMMIT_ALLOW_NO_CONFIG=1 git commit -m "wip"

lint-staged (with Husky)

bash
# Skip lint-staged specifically
SKIP=lint-staged git commit -m "wip"

Method 4: Git Configuration

You can disable hooks entirely at the repository or global level:

bash
1# Disable hooks for this repository
2git config core.hooksPath /dev/null
3
4# Re-enable hooks
5git config --unset core.hooksPath
6
7# Or point to a different hooks directory temporarily
8git config core.hooksPath .git/hooks-disabled

To set this globally (use with caution):

bash
git config --global core.hooksPath /dev/null

Method 5: Git Aliases for Quick Access

If you frequently need to skip hooks, create an alias:

bash
1# Create alias
2git config --global alias.wip '!git commit --no-verify -m'
3
4# Usage
5git wip "work in progress"
6
7# Create alias for amend without hooks
8git config --global alias.amend-quick '!git commit --amend --no-verify --no-edit'

Or add to your shell profile:

bash
# Add to ~/.bashrc or ~/.zshrc
alias gcn='git commit --no-verify'
alias gpn='git push --no-verify'

Usage:

bash
gcn -m "fix: urgent patch"
gpn origin main

When Is It Appropriate to Skip Hooks?

Here is a practical guide:

ScenarioSkip Hooks?Reasoning
Urgent production hotfixYesSpeed matters, CI will catch issues
Work-in-progress commits (will squash later)YesHooks run on the final squashed commit
Fixing the hook itselfYesThe broken hook would prevent its own fix
Merge commits with known conflicts resolvedSometimesIf hooks fail on generated merge markers
Rebasing/amending existing commitsSometimesHooks already passed on original commit
Normal feature developmentNoHooks exist to catch problems early
Commits that go directly to main/productionNoThese commits need the most scrutiny

What Modern Hook Frameworks Do

If your project uses a hook framework, here is how they work and what gets skipped:

Husky (Node.js projects)

Husky installs hooks via a .husky/ directory:

 
.husky/
  pre-commit    # Usually runs lint-staged
  commit-msg    # Usually runs commitlint
bash
1# .husky/pre-commit
2npx lint-staged
3
4# .husky/commit-msg
5npx --no -- commitlint --edit $1

pre-commit (Python projects)

The .pre-commit-config.yaml defines hooks:

yaml
1repos:
2  - repo: https://github.com/pre-commit/pre-commit-hooks
3    rev: v4.6.0
4    hooks:
5      - id: trailing-whitespace
6      - id: end-of-file-fixer
7  - repo: https://github.com/psf/black
8    rev: 24.4.2
9    hooks:
10      - id: black

Selectively skip:

bash
1# Skip only black
2SKIP=black git commit -m "fix: quick patch"
3
4# Skip multiple specific hooks
5SKIP=black,trailing-whitespace git commit -m "fix: quick patch"

lefthook (Go projects and polyglot repos)

yaml
1# lefthook.yml
2pre-commit:
3  commands:
4    lint:
5      run: golangci-lint run
6    test:
7      run: go test ./...
bash
1# Skip lefthook entirely
2LEFTHOOK=0 git commit -m "wip"
3
4# Skip specific commands
5LEFTHOOK_EXCLUDE=test git commit -m "wip: skip tests"

Common Pitfalls

  • Making --no-verify a habit. If you find yourself always skipping hooks, the hooks are either too slow, too strict, or running the wrong checks. Fix the hooks rather than bypassing them permanently. A pre-commit hook should complete in under 5 seconds for it to be practical.
  • Skipping hooks on shared/protected branches. If your team relies on hooks for commit message formatting or lint checks, skipping them on main or develop creates inconsistency. Use server-side hooks or CI checks as a safety net since they cannot be skipped with --no-verify.
  • Forgetting to re-enable hooks. After chmod -x or git config core.hooksPath /dev/null, it is easy to forget that hooks are disabled. Use --no-verify for one-off skips instead, since it does not persist.
  • Assuming --no-verify skips all hooks. It only skips pre-commit and commit-msg. Post-commit hooks still run. Pre-push hooks require git push --no-verify separately.
  • Not setting up CI as a backstop. Client-side hooks are always optional. Any developer can skip them. Critical checks (linting, tests, security scans) should also run in CI, so skipped hooks do not reach production.

Summary

  • Use git commit --no-verify (or -n) to skip pre-commit and commit-msg hooks for a single commit.
  • Use git push --no-verify to skip pre-push hooks.
  • For hook frameworks (Husky, pre-commit, lefthook), use their environment variables to selectively skip specific hooks rather than all of them.
  • Reserve hook skipping for genuine exceptions: hotfixes, WIP commits that will be squashed, and fixing the hooks themselves.
  • Always have CI running the same checks as a safety net, since client-side hooks can always be bypassed.
  • If you frequently need to skip hooks, the hooks are too slow or too aggressive. Fix the underlying problem instead.

Course illustration
Course illustration

All Rights Reserved.