Created
March 21, 2025 18:21
-
-
Save mattsta/3a95f38977ee025ce82f5d6f84585682 to your computer and use it in GitHub Desktop.
git aliases to remove end of line whitespace before committing
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
# git cleancommit <files> | |
# removes trailing end-of-line whitespace in staged or committed files | |
cleancommit = "!bash -c 'commit_args=\"\"; files_to_clean=\"\"; for i in \"$@\"; do if [[ \"$i\" == -* ]]; then commit_args=\"$commit_args $i\"; else if [[ \"$i\" = /* ]]; then files_to_clean=\"$files_to_clean $i\"; else files_to_clean=\"$files_to_clean ${GIT_PREFIX}$i\"; fi; fi; done; if [ -n \"$files_to_clean\" ]; then git diff --name-only -- $files_to_clean | while IFS= read -r file; do if [ -f \"$file\" ]; then temp_file=$(mktemp); git diff -U0 \"$file\" | grep \"^@@\" | awk \"{split(\\$3,a,\\\",\\\"); line=substr(a[1],2); count=(length(a)>1)?a[2]:1; for(i=0;i<count;i++) if(line+i>0) print line+i}\" > \"$temp_file\"; while read -r line_num; do if [ -n \"$line_num\" ] && [[ \"$line_num\" =~ ^[0-9]+$ ]]; then sed -i \"\" \"$line_num s/[[:space:]]*$//\" \"$file\"; fi; done < \"$temp_file\"; rm -f \"$temp_file\"; git add \"$file\"; fi; done; else git diff --cached --name-only --diff-filter=ACM | while IFS= read -r file; do if [ -f \"$file\" ]; then temp_file=$(mktemp); git diff --cached -U0 \"$file\" | grep \"^@@\" | awk \"{split(\\$3,a,\\\",\\\"); line=substr(a[1],2); count=(length(a)>1)?a[2]:1; for(i=0;i<count;i++) if(line+i>0) print line+i}\" > \"$temp_file\"; while read -r line_num; do if [ -n \"$line_num\" ] && [[ \"$line_num\" =~ ^[0-9]+$ ]]; then sed -i \"\" \"$line_num s/[[:space:]]*$//\" \"$file\"; fi; done < \"$temp_file\"; rm -f \"$temp_file\"; git add \"$file\"; fi; done; fi; git commit $commit_args $files_to_clean' --" | |
# git cleandiff <files> | |
# view a diff without end-of-line whitespace | |
cleandiff = "!f() { orig_dir=$(mktemp -d); clean_dir=$(mktemp -d); search_paths=\"\"; if [ $# -eq 0 ]; then search_paths=\".\"; else for arg in \"${@:1}\"; do if [[ \"$arg\" = /* ]]; then search_paths=\"$search_paths $arg\"; else search_paths=\"$search_paths ${GIT_PREFIX}$arg\"; fi; done; fi; git diff --name-only -- $search_paths | while read file; do if [ -f \"$file\" ]; then mkdir -p \"$clean_dir/$(dirname \"$file\")\"; mkdir -p \"$orig_dir/$(dirname \"$file\")\"; cp \"$file\" \"$clean_dir/$file\"; temp_file=$(mktemp); git diff -U0 \"$file\" | grep '^@@' | awk '{split($3,a,\",\"); line=substr(a[1],2); count=(length(a)>1)?a[2]:1; for(i=0;i<count;i++) if(line+i>0) print line+i}' > \"$temp_file\"; while read line_num; do sed -i \"\" \"${line_num}s/[[:space:]]*$//\" \"$clean_dir/$file\"; done < \"$temp_file\"; rm -f \"$temp_file\"; git show HEAD:\"$file\" > \"$orig_dir/$file\" 2>/dev/null || touch \"$orig_dir/$file\"; fi; done; git -c color.diff=always diff --no-index \"$orig_dir\" \"$clean_dir\" 2>/dev/null || true; rm -rf \"$orig_dir\" \"$clean_dir\"; }; f" | |
# why weird shell script aliases instead of pre-commit hooks? git doesn't allow globally shared pre-commit hooks, so you either add things to every repo, or use a global commit hook system which ignores local repos. | |
# By using aliases, you at least get the same commands everywhere. | |
# Also, the ~/.gitconfig format doesn't allow commands to run across mutiple lines, so enjoy all that mess. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment