Git hooks are shell scripts that run automatically before or after Git executes an important command like Commit or Push. They can be used to enforce conventions around git actions, such as branch names and commit messages.
Git hooks reside in .git/hooks. To enable a hook, just remove the .sample extension
Git Hook | Git Command | Description |
applypatch-msg.sample | git am | When a patch message is changed |
commit-msg.sample | git commit | To set the message of a commit action |
fsmonitor-watchman.sample | launch watchman | To integrate watchman |
post-update.sample | git push | By updating all data after the push |
pre-applypatch.sample | git am | Before applying a patch |
pre-commit.sample | git commit | Before committing |
prepare-commit-msg.sample | git commit | When a commit message is set |
pre-push.sample | git push | Before making a push |
pre-rebase.sample | git rebase | Before making a pass or merge |
pre-receive.sample | git push | When we push and get the data from the remote repository |
update.sample | git push | By updating the remote data in a push |
Reference: https://www.hostinger.com/tutorials/how-to-use-git-hooks/
While the directory .git/hooks is not version controlled, you can update your git hooks location to a versioned directory, such as .githooks
> git config core.hooksPath ./.githooks
> git config core.hooksPath ./.githooks
Note: IntelliJIDE does not support custom hook locations, nor prepare-commit-msg
But you can use the plugin Git Commit Message Template w/ a matching regex such as #?[0-9]{6,10}
Branch Names
Having a common naming convention for branches can make it easier to determine what a branch is being used for.
Something like
ticket#-ShortDesc
Branch Names
Having a common naming convention for branches can make it easier to determine what a branch is being used for.
Something like
ticket#-ShortDesc
123123-AddAuditLog
is more useful than
is more useful than
addmorestuff
as you can at least track back the branch back to the originating ticket
The git hook pre-commit can be used to enforce branch names
File pre-commit:
#!/usr/bin/env bash
local_branch="$(git rev-parse --abbrev-ref HEAD)"
#valid_branch_regex="^(feature|bugfix|improvement|library|prerelease|release|hotfix)\/[a-z0-9._-]+$"
valid_branch_regex="^#?[0-9]{6,10}-[a-zA-Z]+$"
error()
{
echo "GIT PRE-COMMIT HOOK ERROR:"
echo "$1"
echo ""
echo "Your commit will be rejected."
echo "You should rename your branch to a valid name and try again."
exit 1
}
if [[ ! $local_branch =~ $valid_branch_regex ]]
then
error "Branch names must match: $valid_branch_regex."
fi
exit 0
as you can at least track back the branch back to the originating ticket
The git hook pre-commit can be used to enforce branch names
File pre-commit:
#!/usr/bin/env bash
local_branch="$(git rev-parse --abbrev-ref HEAD)"
#valid_branch_regex="^(feature|bugfix|improvement|library|prerelease|release|hotfix)\/[a-z0-9._-]+$"
valid_branch_regex="^#?[0-9]{6,10}-[a-zA-Z]+$"
error()
{
echo "GIT PRE-COMMIT HOOK ERROR:"
echo "$1"
echo ""
echo "Your commit will be rejected."
echo "You should rename your branch to a valid name and try again."
exit 1
}
if [[ ! $local_branch =~ $valid_branch_regex ]]
then
error "Branch names must match: $valid_branch_regex."
fi
exit 0
gist
Commit Messages
As git tends to intermingle commits from different branches based on time, you can also enforce comments to contain ticket numbers too.
Something like
ticket# added audit log
as you can at least track back the commit back to the originating ticket
In general, you should try to make multiple commits grouped by concept, and commit every day or two.
The git hooks prepare-commit-msg and commit-msg
can be used to enforce ticket numbers in commits
File prepare-commit-msg:
#!/usr/bin/env bash
# commit message file
commit_msg_file="$1"
# condition the commit is invoked; none (git commit), message (git commit -m <msg>), template, merge, squash, or commit
# commit_source=$2
# commit hash
# sha1=$3
local_branch="$(git rev-parse --abbrev-ref HEAD)"
get_ticket_nbr="^#?([0-9]{6,10}).*"
valid_ticket_nbr="^[0-9]{6,10}$"
error()
Commit Messages
As git tends to intermingle commits from different branches based on time, you can also enforce comments to contain ticket numbers too.
Something like
ticket# added audit log
as you can at least track back the commit back to the originating ticket
In general, you should try to make multiple commits grouped by concept, and commit every day or two.
The git hooks prepare-commit-msg and commit-msg
can be used to enforce ticket numbers in commits
File prepare-commit-msg:
#!/usr/bin/env bash
# commit message file
commit_msg_file="$1"
# condition the commit is invoked; none (git commit), message (git commit -m <msg>), template, merge, squash, or commit
# commit_source=$2
# commit hash
# sha1=$3
local_branch="$(git rev-parse --abbrev-ref HEAD)"
get_ticket_nbr="^#?([0-9]{6,10}).*"
valid_ticket_nbr="^[0-9]{6,10}$"
error()
{
echo "GIT PREPARE-COMMIT HOOK ERROR:"
echo "$1"
echo ""
echo "GIT PREPARE-COMMIT HOOK ERROR:"
echo "$1"
echo ""
exit 1
}
# check if commit message already has the ticket # prepended
# if not, try to prepend
commit_msg=$(cat "$commit_msg_file")
if [[ ! $commit_msg =~ $get_ticket_nbr ]]
then
if [[ $local_branch =~ $get_ticket_nbr ]]
then
ticket="${BASH_REMATCH[1]}"
if [[ $ticket =~ $valid_ticket_nbr ]]
then
echo "#${ticket} " > "$commit_msg_file"
echo "$commit_msg" >> "$commit_msg_file"
fi
fi
fi
exit 0
}
# check if commit message already has the ticket # prepended
# if not, try to prepend
commit_msg=$(cat "$commit_msg_file")
if [[ ! $commit_msg =~ $get_ticket_nbr ]]
then
if [[ $local_branch =~ $get_ticket_nbr ]]
then
ticket="${BASH_REMATCH[1]}"
if [[ $ticket =~ $valid_ticket_nbr ]]
then
echo "#${ticket} " > "$commit_msg_file"
echo "$commit_msg" >> "$commit_msg_file"
fi
fi
fi
exit 0
File commit-msg:
#!/usr/bin/env bash
# commit message file
commit_msg_file="$1"
valid_comment_prefix="^#?[0-9]{6,10} .+"
error()
{
cp "$commit_msg_file" "_gitmsg.saved.txt"
echo "GIT COMMIT-MSG HOOK ERROR:"
echo "$1"
echo ""
echo "Original checkin message has been stored in '_gitmsg.saved.txt'"
echo "Your commit will be rejected."
echo "You should update your commit and try again."
exit 1
}
commit_msg=$(cat "$commit_msg_file")
if [[ ! $commit_msg =~ $valid_comment_prefix ]]
then
error "Comment must match: $valid_comment_prefix"
fi
exit 0
cp "$commit_msg_file" "_gitmsg.saved.txt"
echo "GIT COMMIT-MSG HOOK ERROR:"
echo "$1"
echo ""
echo "Original checkin message has been stored in '_gitmsg.saved.txt'"
echo "Your commit will be rejected."
echo "You should update your commit and try again."
exit 1
}
commit_msg=$(cat "$commit_msg_file")
if [[ ! $commit_msg =~ $valid_comment_prefix ]]
then
error "Comment must match: $valid_comment_prefix"
fi
exit 0
> bash .githooks\prepare-commit-msg test.txt
You should now have some ideas on how to enforce some consistency in your git actions.
You should now have some ideas on how to enforce some consistency in your git actions.
-End of Document-
Thanks for reading