-
Notifications
You must be signed in to change notification settings - Fork 1
Git Hooks
Fisherman supports all standard Git hooks. This reference explains when each hook is triggered, what arguments it receives, and common use cases.
Git hooks are scripts that Git executes before or after events such as commits, pushes, and merges. Fisherman intercepts
these hooks and executes configured rules based on your .fisherman.toml configuration.
Client-side hooks are triggered by local operations like committing and merging.
Triggered: Before a commit is created (after staging files but before entering the commit message)
Can abort: Yes (exit code 1 prevents commit)
Arguments: None
Common use cases:
- Run tests
- Check code formatting
- Run linters
- Validate file contents
- Check for debugging statements or TODO comments
- Ensure no large files are being committed
Example configuration:
[[hooks.pre-commit]]
type = "exec"
command = "cargo"
args = ["test"]
[[hooks.pre-commit]]
type = "exec"
command = "cargo"
args = ["fmt", "--check"]
[[hooks.pre-commit]]
type = "exec"
command = "cargo"
args = ["clippy", "--", "-D", "warnings"]When to use: For validations that should happen before every commit.
Triggered: After the default commit message is generated but before the editor is opened
Can abort: Yes
Arguments:
- Path to commit message file
- Source of commit message (
message,template,merge,squash, orcommit) - Commit SHA (only for
commitsource)
Common use cases:
- Modify commit message template
- Add issue numbers or tags automatically
- Include branch information in commit message
- Insert commit message guidelines
Example configuration:
extract = ["branch?:^(?<IssueNumber>PROJ-\\d+)-.*$"]
[[hooks.prepare-commit-msg]]
type = "write-file"
when = "is_def_var(\"IssueNumber\")"
path = ".git/COMMIT_EDITMSG"
content = "{{IssueNumber}}: "
append = trueWhen to use: To prepare or modify the commit message before the user edits it.
Triggered: After the user enters a commit message but before the commit is created
Can abort: Yes (exit code 1 prevents commit)
Arguments:
- Path to the file containing the commit message
Common use cases:
- Validate commit message format (e.g., Conventional Commits)
- Require issue tracking numbers
- Enforce commit message length
- Check for forbidden words or patterns
- Validate commit message structure
Example configuration:
[[hooks.commit-msg]]
type = "message-regex"
regex = "^(feat|fix|docs|style|refactor|test|chore)(\\(.+\\))?:\\s.+"
[[hooks.commit-msg]]
type = "message-prefix"
prefix = "PROJ-"When to use: To validate or enforce commit message standards.
Triggered: After a commit is created
Can abort: No (commit already created)
Arguments: None
Common use cases:
- Send notifications
- Update logs
- Trigger CI/CD pipelines
- Generate documentation
- Update statistics
Example configuration:
[[hooks.post-commit]]
type = "exec"
command = "notify-send"
args = ["Commit successful", "Changes have been committed"]
[[hooks.post-commit]]
type = "write-file"
path = ".git/commit-log.txt"
content = "Committed at $(date)\n"
append = trueWhen to use: For actions that should happen after a successful commit.
Triggered: Before a rebase operation starts
Can abort: Yes (exit code 1 prevents rebase)
Arguments:
- Upstream branch being rebased onto
- Branch being rebased (optional, only if rebasing a branch other than current)
Common use cases:
- Prevent rebasing protected branches
- Warn about rebasing published commits
- Check for uncommitted changes
Example configuration:
[[hooks.pre-rebase]]
type = "shell"
script = """
if [ "$1" = "master" ]; then
echo "WARNING: Rebasing onto master"
fi
"""When to use: To prevent dangerous rebase operations.
Triggered: After checking out a branch or file
Can abort: No
Arguments:
- Previous HEAD ref
- New HEAD ref
- Flag indicating whether it's a branch checkout (1) or file checkout (0)
Common use cases:
- Update dependencies after branch switch
- Clear caches
- Update commit message templates based on branch
- Display branch-specific information
- Trigger builds
Example configuration:
extract = ["branch?:^(?<IssueNumber>PROJ-\\d+)-.*$"]
[[hooks.post-checkout]]
type = "write-file"
when = "is_def_var(\"IssueNumber\")"
path = ".git/commit_msg_template.txt"
content = "{{IssueNumber}}: "
[[hooks.post-checkout]]
type = "exec"
command = "npm"
args = ["install"]When to use: For actions that should happen after switching branches.
Triggered: After a merge completes successfully
Can abort: No
Arguments:
- Flag indicating whether the merge was a squash merge (1) or not (0)
Common use cases:
- Update dependencies after merge
- Rebuild project
- Send notifications
- Update submodules
Example configuration:
[[hooks.post-merge]]
type = "exec"
command = "npm"
args = ["install"]
[[hooks.post-merge]]
type = "exec"
command = "cargo"
args = ["build"]When to use: To update project state after merging.
Triggered: Before pushing commits to a remote
Can abort: Yes (exit code 1 prevents push)
Arguments:
- Name of remote
- Location of remote
Stdin: Lines with format: <local ref> <local sha> <remote ref> <remote sha>
Common use cases:
- Validate branch names
- Run tests before pushing
- Prevent pushing to protected branches
- Check for secrets or sensitive data
- Verify all tests pass
- Lint code
Example configuration:
[[hooks.pre-push]]
type = "branch-name-regex"
regex = "^(feature|bugfix|hotfix)/[a-z0-9-]+$"
[[hooks.pre-push]]
type = "exec"
command = "cargo"
args = ["test", "--all"]
[[hooks.pre-push]]
type = "shell"
script = """
if git rev-parse --abbrev-ref HEAD | grep -q "^main$"; then
echo "ERROR: Cannot push directly to main branch"
exit 1
fi
"""When to use: To validate changes before they're shared with others.
Triggered: Before applying a patch
Can abort: Yes
Arguments: None
Common use cases:
- Validate patch format
- Check for conflicts
- Run tests
When to use: When working with email-based patches (uncommon in modern workflows).
Triggered: After extracting the patch message but before applying the patch
Can abort: Yes
Arguments:
- Path to file containing the proposed commit message
Common use cases:
- Validate commit message from patch
- Modify commit message before applying
When to use: When working with email-based patches (uncommon in modern workflows).
Triggered: After a patch is applied
Can abort: No
Arguments: None
Common use cases:
- Send notifications
- Update logs
When to use: When working with email-based patches (uncommon in modern workflows).
Triggered: After a merge succeeds but before the merge commit is created
Can abort: Yes (exit code 1 aborts the merge commit)
Arguments: None
Common use cases:
- Validate merge commit message
- Check for merge conflicts in specific files
- Run tests on merged code
Example configuration:
[[hooks.pre-merge-commit]]
type = "exec"
command = "cargo"
args = ["test"]When to use: Similar to pre-commit, but specifically for merge commits.
Triggered: After commits are rewritten (e.g., git commit --amend, git rebase)
Can abort: No
Arguments:
- Name of command that triggered the rewrite (
amendorrebase)
Stdin: Lines with format: <old sha> <new sha>
Common use cases:
- Update references to rewritten commits
- Send notifications about history changes
When to use: To track or respond to commit history changes.
Triggered: Before automatic garbage collection
Can abort: Yes (exit code 1 prevents garbage collection)
Arguments: None
Common use cases:
- Prevent garbage collection during critical operations
- Log garbage collection events
When to use: Rarely needed in normal workflows.
Server-side hooks are triggered by network operations and run on the Git server.
Triggered: When receiving a push, before any references are updated
Can abort: Yes (prevents entire push)
Arguments: None
Stdin: Lines with format: <old sha> <new sha> <ref name>
Common use cases:
- Enforce project-wide policies
- Validate all commits in push
- Check permissions
- Prevent force pushes
When to use: On Git servers to enforce policies for all developers.
Triggered: Once per ref being updated in a push
Can abort: Yes (prevents update of specific ref)
Arguments:
- Name of ref being updated
- Old object name
- New object name
Common use cases:
- Per-branch permissions
- Enforce branch-specific policies
- Prevent updates to protected branches
When to use: On Git servers for per-branch policies.
Triggered: After all references are updated on the server
Can abort: No
Arguments: None
Stdin: Lines with format: <old sha> <new sha> <ref name>
Common use cases:
- Trigger CI/CD pipelines
- Send notifications
- Update documentation
- Deploy applications
- Update issue trackers
When to use: On Git servers to trigger post-push actions.
Triggered: After all references are updated (similar to post-receive)
Can abort: No
Arguments: List of updated refs
Common use cases:
- Update Git repository metadata
- Send email notifications
When to use: On Git servers (post-receive is generally preferred).
Triggered: When pushing to a repository with a checked-out working directory
Can abort: Yes
Arguments:
- Name of ref being updated
Common use cases:
- Update working directory after push
- Deploy to production
When to use: On Git servers with checked-out working directories.
Triggered: When receiving a push for refs matching receive.procReceiveRefs
Can abort: Yes
Arguments: None
Stdin: Lines with format: <old sha> <new sha> <ref name>
Common use cases:
- Custom reference handling
- Integration with external systems
When to use: Advanced server-side scenarios with custom ref processing.
Triggered: At various points during a reference transaction
Can abort: Yes (during prepared state only)
Arguments:
- Transaction state (
prepared,committed,aborted)
Stdin: Lines with format: <old sha> <new sha> <ref name>
Common use cases:
- Audit reference changes
- Implement custom reference policies
When to use: Advanced use cases requiring transaction-level control.
Triggered: After the index (staging area) changes
Can abort: No
Arguments:
- Flag indicating if
index.lockfile existed - Flag indicating if
indexfile was modified
Common use cases:
- Update IDE state
- Regenerate file indexes
- Update build caches
When to use: For development tools that need to respond to staging changes.
Triggered: When Git needs to know which files have changed (if fsmonitor is enabled)
Can abort: No
Arguments:
- Version (currently "2")
- Timestamp of last update
Common use cases:
- Integrate with file system monitoring tools (Watchman)
- Optimize Git operations in large repositories
When to use: For performance optimization in very large repositories.
Triggered: Before sending an email via git send-email
Can abort: Yes
Arguments:
- Path to file containing email to be sent
Common use cases:
- Validate email format
- Check for required headers
When to use: When using git send-email for patch submission.
These hooks are specific to Git's Perforce (P4) integration.
Triggered: When creating a Perforce changelist message
Arguments:
- Name of changelist template file
When to use: When using git-p4 for Perforce integration.
Triggered: After preparing the Perforce changelist message but before editor is opened
Arguments:
- Name of changelist template file
When to use: When using git-p4 for Perforce integration.
Triggered: After a Perforce changelist is submitted
Arguments:
- Name of changelist template file
When to use: When using git-p4 for Perforce integration.
Triggered: Before submitting to Perforce
Can abort: Yes
Arguments: None
When to use: When using git-p4 for Perforce integration.
For most projects, you'll primarily use these hooks:
| Hook | Phase | Can Abort | Common Use |
|---|---|---|---|
pre-commit |
Before commit | Yes | Run tests, check formatting |
commit-msg |
After entering message | Yes | Validate commit message |
post-commit |
After commit | No | Notifications, logging |
post-checkout |
After branch switch | No | Update dependencies, templates |
pre-push |
Before push | Yes | Validate branch, run tests |
post-merge |
After merge | No | Update dependencies |
- Keep hooks fast - Slow hooks interrupt developer workflow
- Use appropriate hooks - Match actions to the right hook lifecycle
- Provide clear error messages - Help developers understand failures
-
Test hooks thoroughly - Use
fisherman handle <hook>to test - Document hook behavior - Explain what each hook does in your configuration
- Use client-side hooks for validation - Server-side hooks for enforcement
-
Make hooks skippable for emergencies - Use
git commit --no-verifywhen necessary - Don't run expensive operations in every hook - Use conditional execution
- Configuration - How to configure hooks
- Rules Reference - Available rule types
- Examples - Real-world examples
- Git Hooks Documentation - Official Git hooks reference