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开发者_StackOverflow) and then commit the reformatting as a separate commit.
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.
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
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
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.
精彩评论