Last active
January 19, 2021 04:25
-
-
Save tamphh/d77fa66dd30fab222b84c23989489210 to your computer and use it in GitHub Desktop.
git hook(bash script) for Rails project to avoid unwanted specific files, keywords (debugger, binding.pry,...) to be commited.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# How to use? | |
# - Save this file as .git/hooks/pre-commit in your project .git folder | |
# - Execute: | |
# chmod +x .git/hooks/pre-commit | |
# | |
# If you want to skip the hook just add the --no-verify flag: | |
# git commit --no-verify | |
# Redirect output to stderr. | |
exec 1>&2 | |
# Color codes | |
red=`tput setaf 1` | |
green=`tput setaf 2` | |
blue=`tput setaf 4` | |
yellow=`tput setaf 3` | |
reset=`tput sgr0` | |
# Notification | |
echo "${blue}" | |
echo "==============================" | |
echo "# Running pre-commit git hook." | |
echo "==============================${reset}" | |
# Debugging functions to be checked. | |
keywords=(debugger binding\.pry puts alert console\.log) | |
# Join keywords array into a single string for grep and remove the separator from the start of the string. | |
keywords_for_grep=$(printf "|%s" "${keywords[@]}") | |
keywords_for_grep=${keywords_for_grep:1} | |
# Directories and files to be excluded during search. | |
exclude_dir_and_ext='\.png$|\.gif$|\.jpg$|\.ico$|\.patch$|\.sh$|\.ttf$|\.woff$|\.eot$|\.svg$' | |
# Files to be prompted | |
files=(schema.rb) | |
# Flag counter | |
debugging_function_found=0 | |
merge_conflict=0 | |
warning_file_found=0 | |
# Check for debugging functions | |
find_debugging_keywords() { | |
FILE=$1 | |
for keyword in "${keywords[@]}" ; do | |
pattern="^\+(.*)?$keyword(.*)?" | |
result_for_file=`git diff --cached $FILE | egrep -x "$pattern"` | |
if [ ! -z "$result_for_file" ] ; then | |
if [ $debugging_function_found -eq 0 ] ; then | |
echo "${red}" | |
echo "# Debugging keywords:" | |
echo "------------------------${reset}" | |
fi | |
debugging_function_found=1 | |
echo "${yellow}" | |
echo " Oops..." "**"$keyword"**" "found:" | |
git grep -n $keyword $FILE | awk '{split($0,a,":"); | |
printf "\t-> " a[1] " on line " a[2] "\n"; | |
}' | |
fi | |
done | |
} | |
# Check for merge conflict markers | |
find_conflict_markers() { | |
FILE=$1 | |
pattern="(<<<<|>>>>)+.*(\n)?" | |
result_for_file=`egrep -in "$pattern" $FILE` | |
if [ ! -z "$result_for_file" ] ; then | |
if [ $merge_conflict -eq 0 ] ; then | |
echo "${red}" | |
echo "# Confict marker(s) found in:" | |
echo "-----------------------------------${reset}" | |
fi | |
merge_conflict=1 | |
echo "${yellow}" | |
echo " ->" $FILE | |
fi | |
} | |
# Check for warning files | |
find_warning_files() { | |
FILE=$(basename "$1") | |
if [ $warning_file_found -eq 0 ] ; then | |
for f in "${files[@]}" ; do | |
if [ "$FILE" = "$f" ] ; then | |
if [ $warning_file_found -eq 0 ] ; then | |
warning_file_found=1 | |
echo "${yellow}" | |
echo "# Warning file(s) found:" | |
echo "------------------------------" | |
echo " ->" $FILE | |
fi | |
fi | |
done | |
fi | |
} | |
# Exit with error | |
exit_with_error() { | |
echo "${red}" | |
echo "Git commit aborted!" | |
echo "${reset}" | |
exit 1 | |
} | |
# List all files added to commit excluding the exceptions | |
files_changed=`git diff-index --diff-filter=ACMRT --cached --name-only HEAD -- | egrep -v $exclude_dir_and_ext` | |
# Find debugging function exists in file diff one by one. | |
if [ -n "$files_changed" ] ; then | |
for FILE in $files_changed ; do | |
find_debugging_keywords $FILE | |
done | |
fi | |
# Find conflict markers exists in file diff one by one. | |
if [ -n "$files_changed" ] ; then | |
for FILE in $files_changed ; do | |
find_conflict_markers $FILE | |
done | |
fi | |
errors_found=$((debugging_function_found+merge_conflict)) | |
# Find warning files. Must execute last. | |
if [ $errors_found -eq 0 ] && [ -n "$files_changed" ] ; then | |
for FILE in $files_changed ; do | |
find_warning_files $FILE | |
done | |
fi | |
# Decision maker | |
if [ $errors_found -eq 0 ] ; then | |
if [ $warning_file_found -eq 0 ] ; then | |
echo "${green}" | |
echo "Codes committed!" | |
echo "${reset}" | |
else | |
exec < /dev/tty | |
while true; do | |
read -p "Warning file(s) would be committed. Are you sure? (y/n) " answer | |
if [[ $answer =~ ^[Yy]$ ]] ; then | |
echo "Accepted" | |
else | |
exit_with_error | |
fi | |
break | |
done | |
fi | |
else | |
exit_with_error | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How to use?
.git/hooks/pre-commit
in your project .git folderchmod +x .git/hooks/pre-commit
to make it executableIf you want to skip the hook just add the
--no-verify
flag:git commit --no-verify
If you want to customize for files, keywords, just modify these contants to meet your need:
Bonus: (thanks to wacko/pre-commit)
$HOME/.git-templates/hooks
$HOME/.gitconfig
:So it will be automatically copied into your project any time you run git init
(you can replace
.git-templates
with any other path)Screen shots:
TODO