66

Is there an easy way to automatically do a git checkout on any file that only has whitespace changes? I'm dealing with both Windows and some code generation that's run from Eclipse, so I get newline changes and whitespace changes that are clogging up my workflow with noise, and making it difficult to track actual changes.

Even just a nice way to report which files have real changes and which don't would be a start, rather than having to do a diff -w for each one

Zombo
  • 1
  • 62
  • 391
  • 407
Sophistifunk
  • 4,742
  • 4
  • 28
  • 37
  • 4
    possible duplicate of [how to "git reset" all files whose only difference is lineendings](http://stackoverflow.com/questions/4027584/how-to-git-reset-all-files-whose-only-difference-is-lineendings) – Keilaron Mar 12 '15 at 18:08
  • 1
    related: [Git add only non-whitespace changes](https://stackoverflow.com/questions/3515597/git-add-only-non-whitespace-changes) – Joshua Goldberg Jul 14 '15 at 14:41
  • This has been answered (note that while the question says only line endings, the answer uses diff -b which is "Ignore changes in the amount of white space"): https://stackoverflow.com/questions/4027584/how-to-git-reset-all-files-whose-only-difference-is-lineendings – Keilaron Mar 12 '15 at 18:07

7 Answers7

144

If your changes are not staged

To stage changes that are not just whitespace changes, you can do:

git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero -

Afterwards, to remove all unstaged changes (those changes that differ only in whitespace), you can do:

git checkout .

If your changes are staged

Unstage your changes by doing a git reset --mixed and continue from the top of this answer. Note that mixed is the default mode and can be omitted.

Kent Munthe Caspersen
  • 5,918
  • 1
  • 35
  • 34
  • 1
    I had a load of files copied down from an FTP to see what was different between my local repo and the remote host, and all the files had different line endings, making it very tedious to identify non-whitespace changes. This worked a treat to identify the one's that were actually different. – theyetiman Jan 31 '19 at 16:12
  • 2
    At first, this didn't work for me because I wasn't in the root directory of the repository (even though it should not be requirement to be in the root directory, I think). So, in case `git apply` returns success (0) without doing anything, try going to the repository's root. – Martin R. Mar 29 '19 at 12:10
  • 1
    Note that if you have `diff.noprefix = true`, the `git apply` above will fail. To fix it, add the option `-p0`. – void.pointer Sep 02 '20 at 13:58
  • 5
    This saved me a billion years... one caveat in my case - it doesn't ignore complete blank lines added/removed. To include that, add `--ignore-blank-lines` to the diff. – MuertoExcobito Feb 12 '21 at 20:06
  • If your changes are commited (and belong exactly to last commit), you can do: ```git reset --soft HEAD~1``` to make them staged, and then follow the instructions above. – ferdymercury Apr 24 '22 at 11:10
  • Those who are lazy do not forget to use an alias like: `clearws = !git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero - && git checkout .` – Maksym Kosenko Aug 01 '22 at 14:20
  • Explain every token of these commands. – Szczepan Hołyszewski Dec 01 '22 at 16:21
  • Thank you for this - after trying bunch of other stuff, this worked like a charm for my case, which included a large number of files. – baky Mar 13 '23 at 18:15
  • A default option such as `git reset --mixed --line-endings` would be really helpful to reset line ending changes automatically. – lanoxx Mar 24 '23 at 10:10
6

This is most likely a line ending issue; Windows uses CRLF (carriage return + line feed, or \r\n) line endings, whereas most other systems use LF (line feed, or \n). Luckily, Git can normalize files such that they are always stored as LF in the repo, but will be checked out as CRLF on Windows. You can do this by setting core.autocrlf to true on Windows:

$ git config --global core.autocrlf true

and setting core.autocrlf to input on Mac and Linux:

$ git config --global core.autocrlf input

More info is available here (scroll down to the section titled core.autocrlf).

mipadi
  • 398,885
  • 90
  • 523
  • 479
  • 1
    I know *why* it's doing it, and I know about core.autocrlf and have it set to true. Neither of these things make it easy to throw away whitespace-only changes made by code generation (such as GraniteDS' plugin spitting out unix newlines even on Windows) – Sophistifunk Dec 10 '12 at 06:19
  • 1
    @moonlightcheese: They changed the Git webpage a few years ago, and apparently got some of the redirects wrong. I updated the URL. – mipadi Nov 07 '17 at 23:11
6

If your changes are commited

(there’s probably a smarter way but this works for me)

mybranch=master
git checkout -b tmp origin/master

# compute the non-ws diff to mybranch and apply it
git diff -U0 -w --no-color $mybranch | git apply -R --cached --ignore-whitespace --unidiff-zero -

git commit -m "non ws changes"
git reset --hard  # discard all non-staged data

Your now on a new "tmp" branch. You may want to clean up (NOTE: this loses history of $mybranch)

git checkout $mybranch
git reset --hard tmp
git branch -D tmp
rumpel
  • 7,870
  • 2
  • 38
  • 39
0

Another approach is to use dos2unix command on a unix or (windows pc as a special install) to convert the line endings and commit and push

Breakpoint25
  • 1,273
  • 1
  • 9
  • 11
0

If your changes are commited and pushed...

...and you are not comfortable with advanced git command line use, but have access to JetBrains Rider IDE or JB family of tools in general, doing mixed git reset via GUI automatically removes whitespace changes. Then just commit. From 200+ files, it only missed one, which I can revert manually.

This procedure can be done 99% via GUI. Right click on base branch in the Git tab, and do reset. It will undo the commit and stage non-whitespaces changes for commit. Now commit and push -f (I always force push via command line). That's it, you are done!

enter image description here

Victor Zakharov
  • 25,801
  • 18
  • 85
  • 151
0

I ended up doing it like this in Powershell 5.1:

# Unstage all pending changes 
git reset

# Create a hashtable to store the files to undo
# By inserting all the files with changes (including whitespace only)
# And then removing the files with real changes 
# Note -w flag indicates to not include whitespace only changes
$files = @{}
git diff --numstat | % { $files.Add($_.Split("`t")[2], $_) }
git diff -w --numstat | % { $files.Remove($_.Split("`t")[2]) }

# Undo the changes
$files.keys | % { git checkout -- $_ }
thepirat000
  • 12,362
  • 4
  • 46
  • 72
-1

rumpel's answer was the right fix for me. I would just like to complete a bit :

If your changes have been pushed

Once you followed rumpel's procedure, do not push again on your branch. Github will ask you to pull before and you will get every whitespace diff again. Instead create a new branch from your current branch and push the new one :

# From $mybranch
git checkout -b $mybranch-v2
git push --set-upstream origin $mybranch-v2

Then on GitHub close and delete $mybranch

Motchouk
  • 9
  • 5
  • i don't see any reason not to forcefully push your own branch if you discussed that with your team – IC_ Sep 13 '21 at 14:18