Skip to content

Instantly share code, notes, and snippets.

@tkrotoff
Last active August 10, 2023 08:51
Show Gist options
  • Save tkrotoff/dc49a8e501b6fdea5a4b66301f7682fc to your computer and use it in GitHub Desktop.
Save tkrotoff/dc49a8e501b6fdea5a4b66301f7682fc to your computer and use it in GitHub Desktop.
Warns about Git staged binary files
#!/usr/bin/env sh
# Warns about Git staged binary files
# https://gist.github.com/tkrotoff/dc49a8e501b6fdea5a4b66301f7682fc
# Capture the output of "git diff" in a temporary file
tmpfile=$(mktemp)
# https://stackoverflow.com/q/28109520
git diff -z --staged --name-only --diff-filter=ACMR > "$tmpfile"
binaries=()
while IFS= read -r -d '' filename; do
# Examples:
#
# $ file --brief --mime README.md
# text/plain; charset=utf-8
#
# $ file --brief --mime typescript.ts
# text/plain; charset=us-ascii
#
# $ file --brief --mime package.json
# application/json; charset=us-ascii
#
# $ file --brief --mime logo.png
# image/png; charset=binary
#
# $ file --brief --mime doc.pdf
# application/pdf; charset=binary
#
mime=$(file --brief --mime "$filename")
if [[ $mime == *"charset=binary" ]]; then
binaries+=("$filename")
fi
done < "$tmpfile"
# Remove the temporary file
rm -f "$tmpfile"
if [[ ${#binaries[@]} -gt 0 ]]; then
for filename in "${binaries[@]}"; do
echo "$filename"
done
echo
echo "Do not clutter Git with large binary files: it cannot be undone"
echo
echo "- Is the file really necessary?"
echo " - Can it be replaced by a link?"
echo " - Will it still be relevant in 3 years?"
echo "- Use the appropriate format (PNG vs JPEG vs SVG)"
echo "- Use appropriate image width × height (are you sure about that 4K image?)"
echo "- Use lossless compression thx to ImageOptim (https://imageoptim.com/mac) or Trimage (https://trimage.org/)"
echo " - Do recompress several times (it might further improve the lossless compression)"
echo
echo "More infos: https://robinwinslow.uk/dont-ever-commit-binary-files-to-git"
echo
echo "Do you want to commit these binaries to the repository? (yes/no)"
# Allows us to read user input below, assigns stdin to keyboard
# https://stackoverflow.com/a/10015707
exec < /dev/tty
read answer
if [[ "$answer" != "${answer#yes}" ]]; then
# Success: Git commit process goes on
exit 0
else
# Failure: Git commit process is aborted
exit 1
fi
else
echo "Good: no staged binary file found"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment