I'm on Mac Mojave. I have created a file at ~/.git-templates/hooks/pre-commit , which I wanted to remove white space from the end of lines in files I'm committing. I would like this to happen globally, across all of my projects.
# A git hook script to find and fix trailing whitespace in your commits. Bypass
# it with the --no-verify option to git-commit.
# detect platform
platform="win"
uname_result=`uname`
if [[ "$uname_result" == "Linux" ]]; then
platform="linux"
elif [[ "$uname_result" == "Darwin" ]]; then
platform="mac"
fi
# change IFS to ignore filename's space in |for|
IFS="
"
# remove trailing whitespace in modified lines
for line in `git diff --check --cached | sed '/^[+-]/d'` ; do
# get file name
if [[ "$platform" == "mac" ]]; then
file="`echo $line | sed -E 's/:[0-9]+: .*//'`"
line_number="`echo $line | sed -E 's/.*:([0-9]+).*/\1/'`"
else
file="`echo $line | sed -r 's/:[0-9]+: .*//'`"
line_number="`echo $line | sed -r 's/.*:([0-9]+).*/\1/'`"
fi
# since $file in working directory isn't always equal to $file in index,
# we backup it; thereby we can add our whitespace fixes without accidently
# adding unstaged changes
backup_file="${file}.working_directory_backup"
cat "$file" > "$backup_file"
git checkout -- "$file" # discard unstaged changes in working directory
# remove trailing whitespace in $file (modified lines only)
if [[ "$platform" == "win" ]]; then
# in windows, `sed -i` adds ready-only attribute to $file (I don't kown why), so we use temp file instead
sed "${line_number}s/[[:space:]]*$//" "$file" > "${file}.bak"
mv -f "${file}.bak" "$file"
elif [[ "$platform" == "mac" ]]; then
sed -i "" "${line_number}s/[[:space:]]*$//" "$file"
else
sed -i "${line_number}s/[[:space:]]*$//" "$file"
fi
git add "$file" # to index, so our whitespace changes will be committed
# restore unstaged changes in $file from its working directory backup, fixing
# whitespace that we fixed above
sed "${line_number}s/[[:space:]]*$//" "$backup_file" > "$file"
rm "$backup_file"
[[ "$platform" == "mac" ]] || e_option="-e" # mac does not understand -e
echo $e_option "Removed trailing whitespace in \033[31m$file\033[0m:$line_number"
done
echo
# credits:
# https://github.com/philz/snippets/blob/master/pre-commit-remove-trailing-whitespace.sh
# https://github.com/imoldman/config/blob/master/pre-commit.git.sh
# If there still are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --
# Now we can commit
exit
So the problem is that it is not trimming the white space at the end of lines. When I open my file after doing a commit, I still see the white space. So my quesiton is how do I fix this? Did I put the hook at the wrong location or is there something else I need to be doing in my file?
You can have two spaces at end of line in markdown and not have it as trailing whitespace by adding " \ " before \n . Turns out git can be convinced to fix whitespace in your working copy via apply. whitespace , by tricking git into treating your working copy changes as a patch.
Git can fix whitespace in patches which you can make use of: git diff --cached --no-color > stage. diff && git apply --index -R stage. diff && git apply --index --whitespace=fix stage.
Trailing whitespace. Description: Used when there is whitespace between the end of a line and the newline.
If you want to manually run all pre-commit hooks on a repository, run pre-commit run --all-files . To run individual hooks use pre-commit run <hook_id> . The first time pre-commit runs on a file it will automatically download, install, and run the hook.
Regarding your script : on your last instrcution before exiting, you probably wanted to call git diff
rather than git diff-index
, didn't you ?
Regarding the action "removing trailing whitespaces from my files before committing" :
most editors allow to run this action on file save, and it is probably the simplest way to have your trailing spaces removed from files you edited yourself
using git specific triggers : a more adapted way would be to use a clean filter in git attributes (see the Keyword Expansion section of the git book) :
This would apply the changes when you "git add" each file, rather than when you commit :
# choose a name for your filter (e.g : 'trimspace'), and write
# the two 'clean' and 'smudge' action :
$ git config filter.trimspace.clean 'sed -e "s/[[:space:]]*$//g"'
$ git config filter.trimspace.smudge cat
# edit the `.gitattributes` file at the root of your repo,
# and target all the files you may want to trim :
$ cat .gitattributes
*.txt filter=trimspace
*.c filter=trimspace
*.py filter=trimspace
...
# from now on : running `git add` will auto trim targeted files when
# they are added to the index
First, make sure the hook is in a folder referenced by a global hook path (available since Git 2.9)
git config --global core.hooksPath /path/to/my/centralized/hooks
Then, check the pre-commit
hook is executable, and actually runs: Add at least one echo at the start, to validate its execution on a commit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With