Git Hooks
Automate task management with Git hooks. Auto-update tasks on commits, start timers on checkout, and enforce branch naming with GitScrum CLI.
Open Source β GitScrum CLI is open source under the MIT license. Available on GitHub and all major package managers. Built for developers β Tasks, timers, sprints, and analytics in your terminal. Git-aware. CI/CD ready.
Automate your workflow with Git hooks. Update task status on commits, start timers on checkout, enforce branch naming conventionsβall without thinking about it.
Quick Reference
gitscrum hooks install # Interactive hook setup
gitscrum hooks list # Show installed hooks
gitscrum hooks remove # Remove hooks
gitscrum hooks test # Test hook executionInstallation
Interactive Setup
gitscrum hooks installWalks you through each hook:
? Install commit-msg hook?
Prepends task ID to commit messages
β― Yes
No
? Install post-checkout hook?
Switches timer to new branch's task
β― Yes
No
? Install pre-push hook?
Updates task status on push
β― Yes
No
β Installed hooks: commit-msg, post-checkout, pre-push
Location: .git/hooks/Install Specific Hooks
gitscrum hooks install commit-msg
gitscrum hooks install pre-push post-checkout
gitscrum hooks install --allDry Run
Preview without installing:
gitscrum hooks install --dry-runAvailable Hooks
commit-msg
Automatically prepends task ID to commit messages.
Trigger: After you write a commit message, before commit is finalized.
# Branch: feature/GS-123-auth-flow
$ git commit -m "add OAuth token refresh"
# Commit message becomes: [GS-123] add OAuth token refreshConfiguration:
# .gitscrum.yml
hooks:
commit_msg:
enabled: true
format: "[{id}] " # Prefix format
skip_if_present: true # Don't add if ID exists
require_task_id: false # Block commits without task ID
exclude_branches: # Skip on these branches
- main
- developBehavior:
| Original Message | Branch | Result |
|---|---|---|
"add login" | feature/GS-123-auth | [GS-123] add login |
"[GS-123] add login" | feature/GS-123-auth | [GS-123] add login (unchanged) |
"add login" | main | add login (excluded) |
"add login" | hotfix-quick | add login (no task ID) |
pre-commit
Runs before commit is created. Use for validation.
Trigger: Before commit, after staging.
hooks:
pre_commit:
enabled: true
require_timer_running: false # Block if no timer
require_time_logged: false # Block if <15 min logged
check_branch_naming: true # Validate branch formatUse Cases:
- Enforce timer usage during work hours
- Validate branch naming conventions
- Check for uncommitted time entries
post-commit
Runs after commit is created.
Trigger: After successful commit.
hooks:
post_commit:
enabled: true
log_commit: true # Log commit in task activity
auto_comment: false # Add commit message as task commentpre-push
Runs before push to remote.
Trigger: After git push, before data is sent.
hooks:
pre_push:
enabled: true
update_status: true # Set task to "In Progress"
stop_timer: false # Stop timer on push
create_backup: false # Backup timer data before pushExample Flow:
$ git push origin feature/GS-123-auth
Running pre-push hook...
β Task GS-123 status updated to "In Progress"
β Push completedpost-checkout
Runs after branch checkout.
Trigger: After git checkout or git switch.
hooks:
post_checkout:
enabled: true
switch_timer: true # Switch timer to new branch's task
show_task: true # Display task info after checkout
auto_start: false # Auto-start timer if task foundExample Flow:
$ git checkout feature/GS-456-payment
Running post-checkout hook...
β Timer switched from GS-123 to GS-456
π GS-456: Implement payment gateway
Status: In Progress | Sprint 15
Estimate: 8 pts | Logged: 2h 15mpost-merge
Runs after successful merge.
Trigger: After git merge or git pull with merge.
hooks:
post_merge:
enabled: true
log_merge: true # Log merge in task activity
close_task: false # Close task if merging to main
stop_timer: true # Stop timer after mergepost-rewrite
Runs after commits are rewritten (rebase, amend).
Trigger: After git rebase or git commit --amend.
hooks:
post_rewrite:
enabled: true
update_references: true # Update task commit referencesHook Configuration
Global Configuration
Apply to all repositories:
# ~/.gitscrum/config.yml
hooks:
commit_msg:
enabled: true
format: "[{id}] "
post_checkout:
enabled: true
show_task: trueProject Configuration
Override for specific project:
# .gitscrum.yml
hooks:
commit_msg:
enabled: true
format: "{id}: " # Different format for this project
require_task_id: trueDisable Specific Hooks
hooks:
post_checkout:
enabled: falseManaging Hooks
List Installed Hooks
gitscrum hooks listπ Installed Hooks
Hook β Status β Source
βββββββββββββββββΌβββββββββββΌββββββββββββββββ
commit-msg β Active β gitscrum
post-checkout β Active β gitscrum
pre-push β Active β gitscrum
pre-commit β Active β husky (external)Test Hooks
Simulate hook execution:
gitscrum hooks test commit-msg --message "add feature"Testing commit-msg hook...
Input: "add feature"
Branch: feature/GS-123-auth
Output: "[GS-123] add feature"
β Hook would execute successfullyRemove Hooks
# Remove specific hook
gitscrum hooks remove commit-msg
# Remove all GitScrum hooks
gitscrum hooks remove --allTemporarily Disable
Skip hooks for a single command:
git commit --no-verify -m "emergency fix"
git push --no-verifyOr set environment variable:
export GITSCRUM_HOOKS_DISABLED=1
git commit -m "skip hooks"Hook Scripts
GitScrum hooks are shell scripts in .git/hooks/:
$ cat .git/hooks/commit-msg
#!/bin/sh
# GitScrum CLI hook - commit-msg
# Installed: 2026-02-07 09:00:00
exec gitscrum hooks run commit-msg "$@"Manual Editing
You can edit hooks directly, but changes may be overwritten:
# Add custom logic before GitScrum hook
#!/bin/sh
# Custom: Check commit message length
if [ $(cat "$1" | wc -c) -lt 10 ]; then
echo "Error: Commit message too short"
exit 1
fi
# GitScrum hook
exec gitscrum hooks run commit-msg "$@"Hook Order
If you have existing hooks, GitScrum appends rather than replaces:
$ gitscrum hooks install commit-msg
Existing commit-msg hook detected.
? How to handle:
β― Append (run both)
Replace (backup existing)
Skip (keep existing)Integration with Other Tools
Husky
GitScrum works alongside Husky:
// package.json
{
"husky": {
"hooks": {
"pre-commit": "lint-staged && gitscrum hooks run pre-commit",
"commit-msg": "gitscrum hooks run commit-msg"
}
}
}Lefthook
# lefthook.yml
commit-msg:
commands:
gitscrum:
run: gitscrum hooks run commit-msg {1}Pre-commit Framework
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: gitscrum-commit-msg
name: GitScrum Commit Message
entry: gitscrum hooks run commit-msg
language: system
stages: [commit-msg]Troubleshooting
Hook Not Running
# Check if hook is executable
ls -la .git/hooks/commit-msg
# Should show: -rwxr-xr-x
# Make executable if needed
chmod +x .git/hooks/commit-msgHook Errors
# Run hook manually to see errors
gitscrum hooks run commit-msg .git/COMMIT_EDITMSGDebug Mode
export GITSCRUM_DEBUG=1
git commit -m "test"
# Shows detailed hook executionReset Hooks
# Remove and reinstall
gitscrum hooks remove --all
gitscrum hooks install --allBest Practices
- Start minimal. Install only hooks you'll use. Add more as needed.
- Test first. Use
--dry-runandhooks testbefore committing to a workflow. - Document for team. Add hook setup to README for new team members.
- Use project config. Put hook settings in
.gitscrum.ymlfor team consistency. - Handle failures gracefully. Hooks shouldn't block valid commits on network errors.
Example Workflows
Strict Tracking
Enforce time tracking on every commit:
hooks:
pre_commit:
enabled: true
require_timer_running: true
commit_msg:
enabled: true
require_task_id: true
post_checkout:
enabled: true
switch_timer: true
auto_start: trueLight Touch
Just add task IDs to commits:
hooks:
commit_msg:
enabled: true
post_checkout:
enabled: true
show_task: trueCI-Friendly
Disable hooks in CI while keeping local:
# CI environment
export GITSCRUM_HOOKS_DISABLED=1