Cron Expression Examples for Common Tasks: Complete Reference
Copy-paste cron expressions for daily backups, weekly reports, monthly cleanups, and more. Ready-to-use examples with explanations for Unix, Kubernetes, and AWS.
I used to push broken code constantly. Now my git hooks catch linting errors, run tests, and validate commits before they embarrass me. Here's my exact setup.
I'll be honest: I resisted git hooks for years. They felt like unnecessary friction. Then I pushed a syntax error to production on a Friday afternoon. That was the last time.
Now I can't imagine working without them. My pre-commit hooks catch formatting issues, linting errors, and TypeScript problems before they ever enter the git history. My pre-push hooks run the full test suite. It's saved me countless embarrassing moments.
This is my exact setup that I use at Šikulovi s.r.o. and on CodeUtil. It's fast (under 2 seconds for most commits), and it catches 90% of the stupid mistakes I used to make.
Git hooks are executable scripts in the .git/hooks directory. Git runs them at specific points: before commits, after merges, before pushes, and many other events. If a hook exits with a non-zero status, Git aborts the operation.
Client-side hooks run on developer machines during local operations. Server-side hooks run on the Git server during push operations. This guide focuses on client-side hooks, which developers control directly.
By default, hooks are local to each repository clone and not tracked in version control. This creates a problem: how do you ensure all team members use the same hooks? Tools like Husky solve this by installing hooks from versioned configuration.
Different hooks serve different purposes. Understanding when each runs helps you choose the right hook for each task.
Pre-commit hooks are the most commonly used. They run after you type git commit but before the commit is created. Use them for linting, formatting, and quick checks. Keep them fast—slow pre-commit hooks frustrate developers.
Commit-msg hooks validate commit messages. They receive the commit message file as an argument. Use them to enforce conventional commits, check for ticket references, or prevent meaningless messages like "fix".
Pre-push hooks run before code is pushed to a remote. They are ideal for running full test suites, type checking, or other slow but important verifications. Failures prevent the push without affecting local commits.
Post-checkout and post-merge hooks run after these operations complete. Use them to install dependencies, rebuild assets, or notify developers of required actions after branch changes.
Husky is the standard tool for managing Git hooks in JavaScript projects. It installs hooks from your package.json configuration, ensuring all team members use the same hooks.
Install Husky as a dev dependency: npm install -D husky. Initialize it with npx husky init, which creates a .husky directory and adds a prepare script to package.json.
Husky stores hooks as shell scripts in the .husky directory. These scripts are tracked in version control, so team members get them automatically. Each hook file must be executable.
For non-JavaScript projects, Husky still works if you have Node.js installed. Alternatively, use lefthook (Go) or pre-commit (Python) for language-agnostic hook management.
Running linters on the entire codebase is slow. lint-staged runs tools only on files staged for commit, making hooks fast while still catching issues.
Install lint-staged: npm install -D lint-staged. Configure it in package.json or a separate .lintstagedrc file. Map file patterns to commands.
lint-staged passes matched filenames to your commands. This allows formatters to fix files and re-stage them automatically. The staged changes, not the working directory, are what gets checked.
Combine multiple tools for different file types. Run ESLint on JavaScript, Prettier on all supported files, and specific linters for other languages. Order matters—run formatters before linters when both might modify files.
Consistent commit messages improve repository history readability. Enforcing formats through hooks ensures every commit follows your conventions.
Conventional Commits is a popular format: type(scope): description. Types include feat, fix, docs, style, refactor, test, and chore. This format enables automatic changelog generation and semantic versioning.
Use the Regex Tester to develop and test your commit message pattern before adding it to hooks. Common patterns check for type prefixes, issue references, or minimum message lengths.
Tools like commitlint provide ready-made commit message validation. Configure rules in commitlint.config.js and run commitlint --edit in your commit-msg hook. For simple patterns, a custom regex check may suffice.
Pre-push hooks run longer verifications that would slow down commits. Use them for test suites, type checking, or build verification.
Create .husky/pre-push with your test command. The hook runs every time you push. If tests fail, the push is blocked, keeping broken code out of remote branches.
Consider what should run on push versus in CI. Pre-push hooks provide instant feedback but run only on the pushing machine. CI runs on clean environments with consistent configurations. Both are valuable.
For large test suites, run only tests related to changed files. Tools like Jest provide options to run tests for changed files. Balance thoroughness with developer experience.
A complete Git hooks setup combines multiple hooks for different purposes. Each hook has specific responsibilities that together ensure code quality.
Pre-commit: Run lint-staged for fast checks on staged files. Format code, run quick lints, check for debugging statements or console.logs.
Commit-msg: Validate commit message format. Ensure it follows conventions, references issues, or meets minimum length requirements.
Pre-push: Run full test suite and type checking. These slower checks verify the codebase before it reaches remote branches.
The key is balance. Too many slow hooks frustrate developers; they will find ways to skip them. Fast, valuable checks maintain compliance without creating friction.
Git hooks occasionally cause problems. Understanding common issues helps you debug and fix them quickly.
Hook not running: Check that the hook file is executable (chmod +x). Verify Husky is installed correctly by checking that .git/hooks/pre-commit points to Husky.
Hook runs but wrong command: Inspect the hook file in .husky directory. Ensure the command is correct and dependencies are installed.
lint-staged not finding files: Check your glob patterns. Use lint-staged --debug to see what files match. Remember that only staged files are processed.
Permission errors on Windows: Line endings matter. Ensure hook files use LF, not CRLF. Git can auto-convert with core.autocrlf settings.
Bypassing hooks: Developers can skip hooks with --no-verify. This is sometimes necessary for emergencies. Monitor for abuse and address root causes of skipping.
Hooks work best when the team agrees on their value and understands their purpose. Roll out gradually and communicate clearly.
Start with minimal hooks and expand. A single formatting hook is easier to accept than a dozen rules at once. Add hooks when specific problems arise.
Document your hooks. Explain what each hook does, why it exists, and how to troubleshoot issues. Include this in your project README or contributing guide.
Make hooks fixable. When possible, hooks should fix issues automatically rather than just reporting them. Auto-formatting is better than format checking.
Handle the escape hatch. --no-verify exists for emergencies. Make it clear when skipping is acceptable and ensure CI catches anything hooks would have caught.
Beyond basic linting and testing, hooks can automate sophisticated workflows tailored to your project needs.
Secret detection: Check staged files for API keys, passwords, or tokens before they enter history. Tools like gitleaks or detect-secrets scan for patterns. Use the Regex Tester to validate detection patterns.
Branch name validation: Enforce naming conventions like feature/TICKET-123-description. Pre-commit or pre-push hooks can verify branch names match required patterns.
Automatic ticket linking: Extract ticket numbers from branch names and prepend them to commit messages. The prepare-commit-msg hook can modify the message before the editor opens.
Size limits: Prevent accidentally committing large files. Check file sizes in pre-commit and block commits that include unexpectedly large binaries.
git commit --no-verify or git push --no-verify. I use it maybe once a month for genuine emergencies. If you're using it daily, your hooks are probably too slow or too strict.
You're probably linting the whole codebase. Use lint-staged - it only checks staged files. My pre-commit runs in under 2 seconds now. Put slow stuff like full test suites in pre-push instead.
Husky handles this automatically. Store hooks in .husky/ directory (tracked in git). When they run npm install, Husky installs the hooks. No manual setup needed.
Pre-commit: fast stuff that runs on every commit (linting, formatting). Pre-push: slow stuff that runs before sharing code (full tests, type checking). Keep pre-commit under 5 seconds.
commitlint + commit-msg hook. I use Conventional Commits format. Test your regex pattern with the Regex Tester before deploying it - broken commit message validation is really annoying.
Founder of CodeUtil. Web developer building tools I actually use. When I'm not coding, I experiment with productivity techniques (with mixed success).
Copy-paste cron expressions for daily backups, weekly reports, monthly cleanups, and more. Ready-to-use examples with explanations for Unix, Kubernetes, and AWS.
Cron expressions have caused me more 3 AM incidents than I care to admit. Here is my guide to validating them properly, plus every mistake I have made so you do not have to.
Master cron expressions with this comprehensive guide. Learn cron syntax, common scheduling patterns, timezone handling, special strings, testing strategies, and platform differences for Linux, AWS, Kubernetes, and more.