Skip to content

Instantly share code, notes, and snippets.

@bitinn
Last active September 5, 2024 06:50
Show Gist options
  • Save bitinn/834756d57f3d47df97937aab68162ae6 to your computer and use it in GitHub Desktop.
Save bitinn/834756d57f3d47df97937aab68162ae6 to your computer and use it in GitHub Desktop.
pre-commit hook to prevent large file on git commit (and allow git-lfs tracked binary files to pass through)
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
# Redirect output to stderr.
exec 1>&2
FILE_SIZE_LIMIT_KB=1024
CURRENT_DIR="$(pwd)"
COLOR='\033[01;33m'
NOCOLOR='\033[0m'
HAS_ERROR=""
COUNTER=0
# generate file extension filter from gitattributes for git-lfs tracked files
filter=$(cat .gitattributes | grep filter=lfs | awk '{printf "-e .%s$ ", $1}')
# before git commit, check non git-lfs tracked files to limit size
files=$(git diff --cached --name-only | sort | uniq | grep -v $filter)
while read -r file; do
if [ "$file" = "" ]; then
continue
fi
file_path=$CURRENT_DIR/$file
file_size=$(ls -l "$file_path" | awk '{print $5}')
file_size_kb=$((file_size / 1024))
if [ "$file_size_kb" -ge "$FILE_SIZE_LIMIT_KB" ]; then
echo "${COLOR}${file}${NOCOLOR} has size ${file_size_kb}KB, over commit limit ${FILE_SIZE_LIMIT_KB}KB."
HAS_ERROR="YES"
((COUNTER++))
fi
done <<< "$files"
# exit with error if any non-lfs tracked files are over file size limit
if [ "$HAS_ERROR" != "" ]; then
echo "$COUNTER files are larger than permitted, please fix them before commit" >&2
exit 1
fi
exit 0
@dfroger
Copy link

dfroger commented Jun 5, 2022

on GNU/Linux, I switch to #!/bin/bash (because of the <<< at line 37), and to echo -e.

@Francois-JEAN
Copy link

Francois-JEAN commented Oct 21, 2022

If there is a space in username, there is a problem when retrieving the file size.
Line 30 can be replace by file_size=$(stat --printf="%s" "$file_path")

And to avoiding testing deleted file Line 24 can be replace by files=$(git diff --cached --name-only --diff-filter=d | sort | uniq | grep -v $filter)

@Dunedan
Copy link

Dunedan commented Sep 5, 2024

Instead of manually parsing .gitattributes, there is also git check-attr, which is less error prone to use and also works with bare repositories.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment