How can I do git add with patch mode but ignoring whitespace changes.
The use case is for when you've reformatted a file and also made changes to it. I want to commit the real code changes separately first (as shown by git diff -w path) and then commit the reformatting as a separate commit.
Note: This answer is old. 6 years down the road, the other answer by Justin is much better. Prefer to use git apply --cached
I suggest simply roundtripping a diff
Idea:
git diff --ignore-all-space | (git reset --hard && git apply)
Warning: this is fraught with danger because of the git reset
there (it will not preserve changes to binary files as written). Perhaps you'd want a bash function similar to
function cleanup_patch()
{
if [ $# -lt 1 ]; then
echo 'Must provide explicit paths (wildcards allowed)';
else
git diff --ignore-all-space -- "$@" |
(git checkout HEAD -- "$@" &&
git apply)
fi
}
Afaict the seemingly useful --binary
option to diff doesn't honour the whitespace ignore flags
Here's an adaptation from a related question.
git diff -w --no-color | git apply --cached --ignore-whitespace
It has the benefit that you don't need to use stash
, temporary files, or perform a reset --hard
on your working folders.
Addendum
The solution above only stages changes except whitespace-only edits. This did not address patch, though using --patch
to stage isn't straight forward in this situation.
Patch Option 1: Edit the diff in a text editor
There are many ways to implement this using a text editor. Vim is especially suited to this.
In the root directory of your repository, start Vim.
In normal mode, load the diff into an empty buffer with...
:r !git diff -w --no-color
:set ft=diff # if you want syntax highlighting
Edit the diff and remove the parts you don't want to stage.
To stage the contents of the vim buffer, run the vim ex command...
:w !git apply --cached --ignore-whitespace
If you're a Vim afficionado, you could use visual mode to stage, too!
:<',>'w !git apply --cached --ignore-whitespace
You can commit the staged changes with the ex command...
:!git commit -m "message"
# or
:!git commit
Clear the buffer, read the unstaged changes, and repeat
:bd! | set ft=diff | r !git diff -w --no-color
Eventually, you'll be left with only whitespace changes to commit.
If you don't use Vim, you could also dump git diff
into a file, edit the file, save, then feed the file into git apply
. Commit and repeat until done. It's a bit tedious, but functional.
Patch Option 2: Patch reset
It's backwards from git add --patch
, but once you've staged non-whitespace changes with...
git diff -w --no-color | git apply --cached --ignore-whitespace
...you can unstage chunks in patch mode with...
git reset --patch .
Keep in mind you're removing the changes that you want to keep staged. Repeat and commit as necessary until you only have whitespace changes left.
A more robust and versatile version of @"Justin C"s answer is:
anw = !git diff -U0 -w --no-color -- \"$@\" | git apply --cached --ignore-whitespace --unidiff-zero "#"
- With no argument - adds all tracked files' non-whitespace changes
- Given files/directories - only adds non-whitespace changes in those locations
See this answer for more.
If you want to do git add --patch but ignore all whitespace like the asker is asking, you can do this in one command:
git diff -w --no-color | git apply --cached --ignore-whitespace && git checkout -- . && git reset && git add -p
git diff -w --no-color
creates a diff
git apply --cached --ignore-whitespace
applies the diff ignoring whitepace, and indexes it
git checkout -- .
removes the unindexed “whitespace” changes
git reset
resets the index to just the non-whitespace changes
git add -p
adds the non-whitespace changes in patch mode
Wrap this up in an alias, like so:
alias gwap=“git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero && git checkout -- . && git reset && git add -p”
Or if you're on a unix based system like I am:
gwap= !git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero && git checkout -- . && git reset && git add -p
(Notice I added options -U0
, and --unidiff-zero
respectively to workaround context matching issues, according to this comment.)
Source: https://til.hashrocket.com/posts/696df00135-remove-whitespace-changes-then-git-add-p