32

The style of my project does say to trim trailing whitespace, but this makes diffs very, very messy. I like to consolidate them to one commit before I commit the actual fix.

This is closely related to Add only non-whitespace changes, but it is asking the exact opposite:

Is there a way to add only the whitespace changes to the staging area?

Community
  • 1
  • 1
Sean Allred
  • 3,558
  • 3
  • 32
  • 71

3 Answers3

45

You can try the following "trick":

git add -A
git diff --cached -w | git apply --cached -R

This basically adds everything to the index, then unstages all changes which affect more than whitespace.

nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • 1
    Related, for creating a git alias: http://stackoverflow.com/a/19525426/1443496. It doesn't appear there is any clever trick to allow piping in an alias, so you must defer to a shell. – Sean Allred Dec 15 '14 at 17:17
  • This has slightly strange behavior when the file pre-normalization has two new lines at the tail (where normalization trims this to one). – Sean Allred Dec 15 '14 at 18:36
  • @SeanAllred: Admittedly not a case I tested (I usually leave only one newline at the tail). What happens in that case? – nneonneo Dec 15 '14 at 18:37
  • [This](https://gist.github.com/vermiculus/c7e8943d2187fcc4798f) is printed and the hunk is left unstaged. I usually leave only one as well, but these files are *very* messy. I like to think I'm doing a public service. – Sean Allred Dec 15 '14 at 18:41
  • I have the prefix disabled, and only got "file is not in index" messages. I needed to add `-p` as option to git apply. – cweiske Mar 13 '20 at 13:08
  • If you get `error: unrecognized input` you might have set coloring in your git config. Doing `git diff --cached -w --color=never | git apply --cached -R` (i.e. disabling output coloring in the diff command) solved this issue for me. – danba Apr 25 '22 at 07:36
3

here is a bash solution that worked for me

for fname in $(git diff --name-only  --diff-filter=ACMR --full-index HEAD)
do
   diff=$(git diff -w --ignore-blank-lines --exit-code $fname)
   if [ $? -eq 0 ]; then
      echo "only whitespace diff on $fname ! adding to git..."
      git add $fname
   else
      echo "diff on $fname!"
   fi
done
Tobias
  • 51
  • 3
  • If your filenames contain spaces, this solution won't work. Modifying it based on https://stackoverflow.com/a/48583007/5078095 was able to get it to work. – gbear605 Dec 02 '21 at 16:10
1

I had to combine and modify Tobias' and nneonneo's answer to commit the whitespace of multiple files with large diffs. Make sure to run this from the root of your repository.

git add -A
for FILE_NAME in $(git --no-pager diff --name-only --diff-filter=ACMR --full-index HEAD)
do  
    git --no-pager diff --cached -w $FILE_NAME | git apply --cached -R  
done

git --no-pager prevents the default scrolling that git uses to display large amounts of content. The --name-only loop allows the command to work on multiple files.

pLiKT
  • 120
  • 1
  • 1
  • 9